From 8dd9b4378b8a6b63efb1528b174d12fd93f6ca8a Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Wed, 4 Feb 2026 08:32:09 -0300 Subject: [PATCH 001/162] docs: pt_BR: Add initial Portuguese translation Introduce the initial Portuguese (Brazilian) translation for the Linux kernel documentation (HOWTO document). It establishes the directory structure for the pt_BR locale and adds the official entry for the pt_BR maintainer in the MAINTAINERS file. Additionally, this version adds pt_BR support to the documentation build script (Documentation/sphinx/translations.py) to ensure proper rendering and fixes the documentation hierarchy to avoid orphan file warnings. Signed-off-by: Daniel Pereira Acked-by: Randy Dunlap Tested-by: Randy Dunlap [jc: fix duplicate process_howto label] Signed-off-by: Jonathan Corbet Message-ID: <20260204113210.185221-1-danielmaraboo@gmail.com> --- Documentation/sphinx/translations.py | 1 + Documentation/translations/index.rst | 4 +- .../translations/pt_BR/disclaimer-pt_BR.rst | 11 + Documentation/translations/pt_BR/index.rst | 69 ++ .../translations/pt_BR/process/howto.rst | 637 ++++++++++++++++++ MAINTAINERS | 6 + 6 files changed, 726 insertions(+), 2 deletions(-) create mode 100644 Documentation/translations/pt_BR/disclaimer-pt_BR.rst create mode 100644 Documentation/translations/pt_BR/index.rst create mode 100644 Documentation/translations/pt_BR/process/howto.rst diff --git a/Documentation/sphinx/translations.py b/Documentation/sphinx/translations.py index 32c2b32b2b5e..a03d4402b4f1 100644 --- a/Documentation/sphinx/translations.py +++ b/Documentation/sphinx/translations.py @@ -25,6 +25,7 @@ all_languages = { 'it_IT': 'Italian', 'ja_JP': 'Japanese', 'ko_KR': 'Korean', + 'pt_BR': 'Portuguese (Brazilian)', 'sp_SP': 'Spanish', } diff --git a/Documentation/translations/index.rst b/Documentation/translations/index.rst index b826c34791c0..b6d24f6f17d1 100644 --- a/Documentation/translations/index.rst +++ b/Documentation/translations/index.rst @@ -10,11 +10,11 @@ Translations zh_CN/index zh_TW/index it_IT/index - ko_KR/index ja_JP/index + ko_KR/index + pt_BR/index sp_SP/index - .. _translations_disclaimer: Disclaimer diff --git a/Documentation/translations/pt_BR/disclaimer-pt_BR.rst b/Documentation/translations/pt_BR/disclaimer-pt_BR.rst new file mode 100644 index 000000000000..3cae22c13d3f --- /dev/null +++ b/Documentation/translations/pt_BR/disclaimer-pt_BR.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + + + +Aviso sobre traduções para português +==================================== + +Esta documentação foi traduzida para português brasileiro por voluntários. +Em caso de qualquer divergência entre esta tradução e o documento original +em inglês, a versão em inglês (encontrada no diretório Documentation/) +deve ser considerada a única fonte de verdade. diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst new file mode 100644 index 000000000000..44fafb3c790a --- /dev/null +++ b/Documentation/translations/pt_BR/index.rst @@ -0,0 +1,69 @@ +.. SPDX-License-Identifier: GPL-2.0 + + + +========================================= +Documentação do Kernel Linux em Português +========================================= + +.. raw:: latex + + \kerneldocCJKoff + +:mantenedor: Daniel Pereira + +Este é o nível principal da documentação do kernel em língua portuguesa (Brasil). +A tradução ainda está em seu estágio inicial e incompleta; você notará avisos +sinalizando a falta de traduções para grupos específicos de documentos. + +De maneira geral, a documentação, assim como o próprio kernel, está em constante +desenvolvimento; isso é especialmente verdade agora, pois estamos trabalhando +na reorganização da documentação de forma mais coerente. Melhorias na +documentação são sempre bem-vindas; se você deseja ajudar, inscreva-se na lista +de discussão linux-doc em vger.kernel.org. + + + +Avisos +====== + +.. include:: disclaimer-pt_BR.rst + +O objetivo desta tradução é facilitar a leitura e compreensão para aqueles que +não dominam o inglês ou têm dúvidas sobre sua interpretação, ou simplesmente +para quem prefere ler em sua língua nativa. No entanto, tenha em mente que a +*única* documentação oficial é a em língua inglesa: :ref:`linux_doc` + +A propagação simultânea de uma alteração em :ref:`linux_doc` para todas as +traduções é altamente improvável. Os mantenedores das traduções — e seus +contribuidores — acompanham a evolução da documentação oficial e tentam manter +as respectivas traduções alinhadas na medida do possível. Por este motivo, não +há garantia de que uma tradução esteja atualizada com a última modificação. +Se o que você ler em uma tradução não corresponder ao que ler no código, +informe o mantenedor da tradução e — se puder — verifique também a +documentação em inglês. + +Uma tradução não é um *fork* da documentação oficial; portanto, os usuários não +encontrarão nela informações diferentes daquelas contidas na versão oficial. +Qualquer adição, remoção ou modificação de conteúdo deve ser feita primeiro nos +documentos em inglês. Posteriormente, quando possível, a mesma alteração deve +ser aplicada às traduções. Os mantenedores das traduções aceitam contribuições +que afetem puramente a atividade de tradução (por exemplo, novas traduções, +atualizações, correções). + +As traduções buscam ser o mais precisas possível, mas não é possível mapear +diretamente uma língua em outra. Cada língua possui sua própria gramática e +cultura, portanto, a tradução de uma frase em inglês pode ser modificada para +se adaptar ao português. Por esse motivo, ao ler esta tradução, você poderá +encontrar algumas diferenças de forma, mas que transmitem a mensagem original. + +Trabalhando com a comunidade de desenvolvimento +=============================================== + +As guias fundamentais para a interação com a comunidade de desenvolvimento do +kernel e sobre como ver seu trabalho integrado. + +.. toctree:: + :maxdepth: 1 + + Como começar diff --git a/Documentation/translations/pt_BR/process/howto.rst b/Documentation/translations/pt_BR/process/howto.rst new file mode 100644 index 000000000000..35bf633f21d6 --- /dev/null +++ b/Documentation/translations/pt_BR/process/howto.rst @@ -0,0 +1,637 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. pt_process_howto: + +COMO FAZER o desenvolvimento do kernel Linux +============================================ + +Este é o documento definitivo sobre este tópico. Ele contém instruções +sobre como se tornar um desenvolvedor do kernel Linux e como aprender a +trabalhar com a comunidade de desenvolvimento do kernel Linux. Ele tenta +não conter nada relacionado aos aspectos técnicos da programação do kernel, +mas ajudará a apontar a direção certa para isso. + +Se algo neste documento ficar desatualizado, por favor, envie patches para +o mantenedor deste arquivo, que está listado no final do documento. + + +Introdução +------------ + +Então, você quer aprender como se tornar um desenvolvedor do kernel Linux? +Ou o seu gerente lhe disse: "Vá escrever um driver Linux para este +dispositivo". O objetivo deste documento é ensinar tudo o que você precisa +saber para conseguir isso, descrevendo o processo pelo qual você deve passar +e oferecendo dicas sobre como trabalhar com a comunidade. Ele também tentará +explicar algumas das razões pelas quais a comunidade trabalha da forma que +trabalha. + +O kernel é escrito principalmente em C, com algumas partes dependentes de +arquitetura escritas em assembly. Um bom entendimento de C é necessário para +o desenvolvimento do kernel. O conhecimento de Assembly (de qualquer +arquitetura) não é obrigatório, a menos que você planeje fazer +desenvolvimento de baixo nível para essa arquitetura específica. Embora não +sejam um substituto para uma formação sólida em C e/ou anos de experiência, +os seguintes livros são bons para, no mínimo, referência: + + - "The C Programming Language" por Kernighan e Ritchie [Prentice Hall] + + - "Practical C Programming" por Steve Oualline [O'Reilly] + + - "C: A Reference Manual" por Harbison e Steele [Prentice Hall] + +O kernel é escrito usando o GNU C e a GNU toolchain. Embora ele siga o +padrão ISO C11, ele utiliza uma série de extensões que não estão presentes +no padrão. O kernel é um ambiente C independente (freestanding), sem +dependência da biblioteca C padrão (libc), portanto, algumas partes do +padrão C não são suportadas. Divisões arbitrárias de "long long" e ponto +flutuante não são permitidas. Às vezes, pode ser difícil entender as +suposições que o kernel faz sobre a toolchain e as extensões que ele utiliza +e, infelizmente, não existe uma referência definitiva para elas. Por favor, +verifique as páginas de informações do gcc (`info gcc`) para obter algumas +informações sobre elas. + +Por favor, lembre-se de que você está tentando aprender como trabalhar com a +comunidade de desenvolvimento existente. É um grupo diversificado de pessoas, +com altos padrões de codificação, estilo e procedimento. Esses padrões foram +criados ao longo do tempo com base no que se descobriu funcionar melhor para +uma equipe tão grande e geograficamente dispersa. Tente aprender o máximo +possível sobre esses padrões com antecedência, pois eles estão bem +documentados; não espere que as pessoas se adaptem a você ou à forma de fazer +as coisas da sua empresa. + + +Questões Legais +--------------- + +O código-fonte do kernel Linux é lançado sob a GPL. Por favor, veja o arquivo +COPYING no diretório principal da árvore de fontes. As regras de licenciamento +do kernel Linux e como usar os identificadores `SPDX `_ no +código-fonte estão descritas em :ref:`Documentation/process/license-rules.rst `. +Se você tiver mais perguntas sobre a licença, por favor, entre em contato com +um advogado e não pergunte na lista de discussão do kernel Linux. As pessoas +nas listas de discussão não são advogados e você não deve confiar em suas +declarações sobre assuntos jurídicos. + +Para perguntas e respostas comuns sobre a GPL, por favor, veja: + + https://www.gnu.org/licenses/gpl-faq.html + + +Documentação +------------ + +A árvore de fontes do kernel Linux possui uma vasta gama de documentos que +são inestimáveis para aprender como interagir com a comunidade do kernel. +Quando novos recursos são adicionados ao kernel, recomenda-se que novos +arquivos de documentação também sejam adicionados explicando como usar o +recurso. Quando uma mudança no kernel faz com que a interface que o kernel +expõe para o espaço do usuário (userspace) mude, recomenda-se que você envie +a informação ou um patch para as páginas de manual explicando a mudança para +o mantenedor das páginas de manual em alx@kernel.org, e coloque em cópia (CC) +a lista linux-api@vger.kernel.org. + +Aqui está uma lista de arquivos que estão na árvore de fontes do kernel e +que são de leitura obrigatória: + + :ref:`Documentation/admin-guide/README.rst ` + Este arquivo fornece um breve histórico sobre o kernel Linux e descreve + o que é necessário fazer para configurar e compilar o kernel. Pessoas + que são novas no kernel devem começar por aqui. + + :ref:`Documentation/process/changes.rst ` + Este arquivo fornece uma lista das versões mínimas de vários pacotes de + software que são necessários para compilar e executar o kernel com + sucesso. + + :ref:`Documentation/process/coding-style.rst ` + Este documento descreve o estilo de codificação do kernel Linux e parte + da fundamentação por trás dele. Espera-se que todo código novo siga as + diretrizes deste documento. A maioria dos mantenedores apenas aceitará + patches se essas regras forem seguidas, e muitas pessoas apenas + revisarão o código se ele estiver no estilo adequado. + + :ref:`Documentation/process/submitting-patches.rst ` + Este arquivo descreve em detalhes explícitos como criar e enviar + um patch com sucesso, incluindo (mas não limitado a): + + - Conteúdo do e-mail + - Formato do e-mail + - Para quem enviá-lo + + Seguir estas regras não garantirá o sucesso (já que todos os patches + estão sujeitos a um escrutínio de conteúdo e estilo), mas não segui-las + quase sempre o impedirá. + +Outras excelentes descrições de como criar patches adequadamente são: + + "O Patch Perfeito" + https://www.ozlabs.org/~akpm/stuff/tpp.txt + + "Formato de Submissão de Patch do Kernel Linux" + https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html + + :ref:`Documentation/process/stable-api-nonsense.rst ` + Este arquivo descreve a justificativa por trás da decisão consciente de + não ter uma API estável dentro do kernel, incluindo pontos como: + + - Camadas de adaptação (shim-layers) de subsistemas (para compatibilidade?) + - Portabilidade de drivers entre sistemas operacionais. + - Mitigação de mudanças rápidas dentro da árvore de fontes do kernel + (ou impedimento de mudanças rápidas). + + Este documento é crucial para compreender a filosofia de desenvolvimento + do Linux e é muito importante para pessoas que estão migrando para o + Linux vindas do desenvolvimento em outros Sistemas Operacionais. + + :ref:`Documentation/process/security-bugs.rst ` + Se você acredita ter encontrado um problema de segurança no kernel Linux, + por favor, siga os passos descritos neste documento para ajudar a + notificar os desenvolvedores do kernel e auxiliar na resolução do problema. + + :ref:`Documentation/process/management-style.rst ` + Este documento descreve como os mantenedores do kernel Linux operam e o + ethos compartilhado por trás de suas metodologias. Esta é uma leitura + importante para qualquer pessoa nova no desenvolvimento do kernel (ou + para qualquer pessoa simplesmente curiosa sobre isso), pois resolve muitos + equívocos comuns e confusões sobre o comportamento único dos mantenedores + do kernel. + + :ref:`Documentation/process/stable-kernel-rules.rst ` + Este arquivo descreve as regras sobre como ocorrem os lançamentos das + versões estáveis (stable) do kernel e o que fazer se você desejar que + uma alteração seja incluída em um desses lançamentos. + + :ref:`Documentation/process/kernel-docs.rst ` + Uma lista de documentação externa que pertence ao desenvolvimento do + kernel. Por favor, consulte esta lista caso não encontre o que está + procurando dentro da documentação interna do kernel. + + :ref:`Documentation/process/applying-patches.rst ` + Uma boa introdução descrevendo exatamente o que é um patch e como + aplicá-lo aos diferentes ramos (branches) de desenvolvimento do kernel. + +O kernel também possui um grande número de documentos que podem ser +gerados automaticamente a partir do próprio código-fonte ou de +marcações ReStructuredText (ReST), como esta. Isso inclui uma +descrição completa da API interna do kernel e regras sobre como +manipular o bloqueio (locking) corretamente. + +Todos esses documentos podem ser gerados em formato PDF ou HTML ao +executar:: + + make pdfdocs + make htmldocs + +respectivamente, a partir do diretório principal do código-fonte do kernel. + +Os documentos que utilizam a marcação ReST serão gerados em +Documentation/output. Eles também podem ser gerados nos formatos +LaTeX e ePub com:: + + make latexdocs + make epubdocs + +Como se tornar um desenvolvedor do kernel +------------------------------------------ + +Se você não sabe nada sobre o desenvolvimento do kernel Linux, você deve +consultar o projeto Linux KernelNewbies: + + https://kernelnewbies.org + +Ele consiste em uma lista de discussão útil onde você pode fazer quase +qualquer tipo de pergunta básica sobre o desenvolvimento do kernel +(certifique-se de pesquisar nos arquivos primeiro, antes de perguntar +algo que já foi respondido no passado). Ele também possui um canal de +IRC que você pode usar para fazer perguntas em tempo real, e muita +documentação útil para aprender sobre o desenvolvimento do kernel Linux. + +O site possui informações básicas sobre a organização do código, +subsistemas e projetos atuais (tanto in-tree quanto out-of-tree). +Também descreve algumas informações logísticas básicas, como por exemplo, +como compilar um kernel e aplicar um patch. + +Se você não sabe por onde começar, mas deseja procurar alguma tarefa +para iniciar sua integração na comunidade de desenvolvimento do kernel, +acesse o projeto Linux Kernel Janitor: + + https://kernelnewbies.org/KernelJanitors + +É um ótimo lugar para começar. Ele descreve uma lista de problemas +relativamente simples que precisam ser limpos e corrigidos dentro da +árvore de códigos-fonte do kernel Linux. Ao trabalhar com os +desenvolvedores responsáveis por este projeto, você aprenderá o básico +sobre como incluir seu patch na árvore do kernel Linux e, +possivelmente, será orientado sobre o que trabalhar em seguida, caso +ainda não tenha uma ideia. + +Antes de fazer qualquer modificação real no código do kernel Linux, é +imperativo entender como o código em questão funciona. Para esse +propósito, nada é melhor do que lê-lo diretamente (a maioria das partes +complexas está bem comentada), talvez até com a ajuda de ferramentas +especializadas. Uma ferramenta particularmente recomendada é o projeto +Linux Cross-Reference, que é capaz de apresentar o código-fonte em um +formato de página web indexada e auto-referenciada. Um excelente +repositório atualizado do código do kernel pode ser encontrado em: + + https://elixir.bootlin.com/ + + +O processo de desenvolvimento +----------------------------- + +O processo de desenvolvimento do kernel Linux consiste atualmente em algumas +"branches" (ramos) principais diferentes e muitos ramos de subsistemas +específicos. Esses diferentes ramos são: + + - Árvore principal (mainline) do Linus + - Várias árvores estáveis com múltiplos números de versão principal + - Árvores específicas de subsistemas + - Árvore de testes de integração linux-next + +Árvore principal (Mainline tree) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A árvore principal é mantida por Linus Torvalds e pode ser encontrada em +https://kernel.org ou no repositório. Seu processo de desenvolvimento é +o seguinte: + + - Assim que um novo kernel é lançado, uma janela de duas semanas é aberta; + durante esse período, os mantenedores podem enviar grandes diffs para + Linus, geralmente patches que já foram incluídos na linux-next por algumas + semanas. A forma preferida de enviar grandes mudanças é usando o git + (a ferramenta de gerenciamento de código-fonte do kernel, mais informações + podem ser encontradas em https://git-scm.com/), mas patches simples + também são aceitos. + - Após duas semanas, um kernel -rc1 é lançado e o foco passa a ser tornar + o novo kernel o mais sólido possível. A maioria dos patches neste estágio + deve corrigir uma regressão. Bugs que sempre existiram não são regressões, + portanto, envie esses tipos de correções apenas se forem importantes. + Observe que um driver (ou sistema de arquivos) totalmente novo pode ser + aceito após o -rc1 porque não há risco de causar regressões com tal + mudança, desde que a alteração seja autocontida e não afete áreas fora do + código que está sendo adicionado. O git pode ser usado para enviar + patches para Linus após o lançamento do -rc1, mas os patches também + precisam ser enviados para uma lista de discussão pública para revisão. + - Um novo -rc é lançado sempre que Linus considerar que a árvore git atual + está em um estado razoavelmente estável e adequado para testes. O objetivo + é lançar um novo kernel -rc a cada semana. + - O processo continua até que o kernel seja considerado "pronto"; o + processo deve durar cerca de 6 semanas. + +Vale a pena mencionar o que Andrew Morton escreveu na lista de discussão +do kernel Linux sobre os lançamentos do kernel: + + *"Ninguém sabe quando um kernel será lançado, porque ele é + lançado de acordo com o status percebido dos bugs, não de acordo + com um cronograma pré-concebido."* + +Várias árvores estáveis com múltiplos números de versão principal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Kernels com versões de 3 partes são kernels -stable (estáveis). Eles +contêm correções relativamente pequenas e críticas para problemas de +segurança ou regressões significativas descobertas em um determinado +lançamento principal da árvore mainline. Cada lançamento em uma série +estável principal incrementa a terceira parte do número da versão, +mantendo as duas primeiras partes iguais. + +Este é o ramo recomendado para usuários que desejam o kernel estável +mais recente e não estão interessados em ajudar a testar versões de +desenvolvimento ou experimentais. + +As árvores estáveis são mantidas pela equipe "stable" + e são lançadas conforme a necessidade exigir. +O período normal de lançamento é de aproximadamente duas semanas, mas +pode ser mais longo se não houver problemas urgentes. Por outro lado, +um problema relacionado à segurança pode fazer com que um lançamento +ocorra quase instantaneamente. + +O arquivo :ref:`Documentation/process/stable-kernel-rules.rst ` +na árvore do kernel documenta quais tipos de mudanças são aceitáveis para +a árvore -stable e como o processo de lançamento funciona. + +Árvores específicas de subsistemas +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Os mantenedores dos vários subsistemas do kernel — e também muitos +desenvolvedores de subsistemas do kernel — expõem seu estado atual de +desenvolvimento em repositórios de código-fonte. Dessa forma, outros +podem ver o que está acontecendo nas diferentes áreas do kernel. Em +áreas onde o desenvolvimento é rápido, um desenvolvedor pode ser +solicitado a basear suas submissões em tal árvore de subsistema do +kernel para que conflitos entre a submissão e outros trabalhos já em +andamento sejam evitados. + +A maioria desses repositórios são árvores git, mas também existem outros +SCMs em uso, ou filas de patches sendo publicadas como séries quilt. Os +endereços desses repositórios de subsistemas estão listados no arquivo +MAINTAINERS. Muitos deles podem ser navegados em https://git.kernel.org/. + +Antes que um patch proposto seja incluído em tal árvore de subsistema, +ele está sujeito a uma revisão que ocorre principalmente em listas de +discussão (veja a seção respectiva abaixo). Para vários subsistemas do +kernel, este processo de revisão é rastreado com a ferramenta patchwork. +O Patchwork oferece uma interface web que mostra as postagens de patches, +quaisquer comentários sobre um patch ou revisões feitas a ele, e os +mantenedores podem marcar os patches como "sob revisão", "aceitos" ou +"rejeitados". A maioria desses sites patchwork está listada em +https://patchwork.kernel.org/. + +Árvore de testes de integração linux-next +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Antes que as atualizações das árvores de subsistemas sejam mescladas na +árvore mainline, elas precisam ser testadas quanto à integração. Para +este propósito, existe um repositório de testes especial no qual +praticamente todas as árvores de subsistemas são integradas (pulled) +quase diariamente: + + https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git + +Dessa forma, a linux-next oferece uma visão resumida do que se espera +que entre no kernel mainline no próximo período de mesclagem (merge +window). Testadores aventureiros são muito bem-vindos para testar a +linux-next em tempo de execução. + + +Relato de Bugs +-------------- + +O arquivo 'Documentation/admin-guide/reporting-issues.rst' no diretório +principal de códigos-fonte do kernel descreve como relatar um possível +bug no kernel e detalha que tipo de informação é necessária para os +desenvolvedores do kernel ajudarem a rastrear o problema. + +Gerenciando relatos de bugs +--------------------------- + +Uma das melhores maneiras de colocar em prática suas habilidades de hacking +é corrigindo bugs relatados por outras pessoas. Você não apenas ajudará a +tornar o kernel mais estável, mas também aprenderá a resolver problemas do +mundo real, melhorará suas habilidades e outros desenvolvedores passarão a +notar sua presença. Corrigir bugs é uma das melhores formas de obter mérito +entre outros desenvolvedores, pois poucas pessoas gostam de gastar tempo +corrigindo bugs de terceiros. + +Para trabalhar em relatos de bugs já existentes, encontre um subsistema no +qual você esteja interessado. Verifique no arquivo MAINTAINERS para onde +os bugs daquele subsistema são relatados; geralmente será uma lista de +discussão, raramente um rastreador de bugs (bugtracker). Pesquise nos +arquivos de mensagens do local indicado por relatos recentes e ajude onde +achar apropriado. Você também pode verificar o site +https://bugzilla.kernel.org para relatos de bugs; apenas alguns +subsistemas do kernel o utilizam ativamente para relato ou rastreamento, +entretanto, bugs de todo o kernel acabam sendo registrados lá. + + +Listas de discussão +------------------- + +Como alguns dos documentos acima descrevem, a maioria dos desenvolvedores +do núcleo (core) do kernel participa da Linux Kernel Mailing List (LKML). +Detalhes sobre como se inscrever e cancelar a inscrição na lista podem +ser encontrados em: + + https://subspace.kernel.org/subscribing.html + +Existem arquivos de mensagens da lista na web em muitos lugares diferentes. +Use um mecanismo de busca para encontrar esses arquivos. Por exemplo: + + https://lore.kernel.org/linux-kernel/ + +É altamente recomendável que você pesquise nos arquivos sobre o tópico que +deseja abordar antes de postar na lista. Muitas coisas já discutidas em +detalhes estão registradas apenas nos arquivos das listas de discussão. + +A maioria dos subsistemas individuais do kernel também possui sua própria +lista de discussão separada, onde realizam seus esforços de desenvolvimento. +Consulte o arquivo MAINTAINERS para obter uma lista de quais são essas +listas para os diferentes grupos. + +Muitas das listas estão hospedadas no kernel.org. Informações sobre elas +podem ser encontradas em: + + https://subspace.kernel.org + +Por favor, lembre-se de seguir bons hábitos de comportamento ao usar as +listas. Embora um pouco clichê, a URL a seguir possui algumas diretrizes +simples para interagir com a lista (ou qualquer outra lista): + + https://subspace.kernel.org/etiquette.html + +Se várias pessoas responderem ao seu e-mail, a lista de destinatários em +CC: pode se tornar bem grande. Não remova ninguém da lista CC: sem um +bom motivo, e não responda apenas para o endereço da lista. Acostume-se +a receber o e-mail duas vezes (um do remetente e outro da lista) e não +tente ajustar isso adicionando cabeçalhos de e-mail complexos; as pessoas +não gostarão disso. + +Lembre-se de manter o contexto e a atribuição de suas respostas intactos; +mantenha as linhas do tipo "John Kernelhacker escreveu...:" no topo da +sua resposta e adicione seus comentários entre as seções citadas +individualmente, em vez de escrever tudo no topo do e-mail. + +Se você adicionar patches ao seu e-mail, certifique-se de que sejam texto +puro legível, conforme declarado em +:ref:`Documentation/process/submitting-patches.rst `. +Os desenvolvedores do kernel não querem lidar com anexos ou patches +compactados; eles podem querer comentar linhas individuais do seu patch, +o que só funciona dessa forma. Certifique-se de usar um programa de +e-mail que não altere espaços e caracteres de tabulação (tabs). Um bom +primeiro teste é enviar o e-mail para si mesmo e tentar aplicar o seu +próprio patch. Se isso não funcionar, conserte seu programa de e-mail ou +troque-o até que funcione. + +Acima de tudo, por favor, lembre-se de mostrar respeito aos outros +inscritos. + + +Trabalhando com a comunidade +---------------------------- + +O objetivo da comunidade do kernel é fornecer o melhor kernel possível. +Quando você envia um patch para aceitação, ele será revisado por seus +méritos técnicos e apenas por eles. Então, o que você deve esperar? + + - críticas + - comentários + - solicitações de mudança + - solicitações de justificativa + - silêncio + +Lembre-se, isso faz parte do processo de incluir seu patch no kernel. +Você deve ser capaz de aceitar críticas e comentários sobre seus patches, +avaliá-los em nível técnico e retrabalhar seus patches ou fornecer +raciocínios claros e concisos sobre o porquê de certas mudanças não +deverem ser feitas. Se não houver respostas à sua postagem, aguarde +alguns dias e tente novamente; às vezes, as coisas se perdem no enorme +volume de mensagens. + +O que você não deve fazer? + + - esperar que seu patch seja aceito sem questionamentos + - tornar-se defensivo + - ignorar comentários + - reenviar o patch sem fazer nenhuma das alterações solicitadas + +Em uma comunidade que busca a melhor solução técnica possível, sempre +haverá opiniões divergentes sobre o quão benéfico é um patch. Você deve +ser cooperativo e estar disposto a adaptar sua ideia para que ela se +encaixe no kernel. Ou, pelo menos, estar disposto a provar que sua ideia +vale a pena. Lembre-se: estar errado é aceitável, desde que você esteja +disposto a trabalhar em direção a uma solução correta. + +É normal que as respostas ao seu primeiro patch sejam apenas uma lista +de uma dúzia de coisas que você deve corrigir. Isso **não** implica que +seu patch não será aceito e **não** é algo pessoal contra você. Simplesmente +corrija todos os problemas apontados em seu patch e envie-o novamente. + + +Diferenças entre a comunidade do kernel e estruturas corporativas +----------------------------------------------------------------- + +A comunidade do kernel trabalha de forma diferente da maioria dos ambientes +tradicionais de desenvolvimento corporativo. Aqui está uma lista de coisas +que você pode tentar fazer para evitar problemas: + + Boas coisas a dizer em relação às suas mudanças propostas: + + - "Isto resolve múltiplos problemas." + - "Isto remove 2000 linhas de código." + - "Aqui está um patch que explica o que estou tentando descrever." + - "Eu testei isso em 5 arquiteturas diferentes..." + - "Aqui está uma série de pequenos patches que..." + - "Isto aumenta a performance em máquinas comuns..." + + Coisas ruins que você deve evitar dizer: + + - "Nós fizemos desta forma no AIX/ptx/Solaris, portanto deve ser bom..." + - "Eu faço isso há 20 anos, então..." + - "Isto é necessário para minha empresa ganhar dinheiro." + - "Isto é para nossa linha de produtos Enterprise." + - "Aqui está meu documento de design de 1000 páginas que descreve minha ideia." + - "Estou trabalhando nisso há 6 meses..." + - "Aqui está um patch de 5000 linhas que..." + - "Eu reescrevi toda a bagunça atual, e aqui está..." + - "Eu tenho um prazo (deadline), e este patch precisa ser aplicado agora." + +Outra forma em que a comunidade do kernel difere da maioria dos ambientes +tradicionais de engenharia de software é a natureza anônima da interação. +Um benefício de usar e-mail e IRC como as principais formas de comunicação +é a ausência de discriminação baseada em gênero ou raça. O ambiente de +trabalho do kernel Linux aceita mulheres e minorias porque tudo o que você +é, é um endereço de e-mail. O aspecto internacional também ajuda a nivelar +o campo de jogo porque você não pode adivinhar o gênero com base no nome +de uma pessoa. Um homem pode se chamar Andrea e uma mulher pode se chamar +Pat. A maioria das mulheres que trabalharam no kernel Linux e expressaram +uma opinião tiveram experiências positivas. + +A barreira do idioma pode causar problemas para algumas pessoas que não +se sentem confortáveis com o inglês. Um bom domínio do idioma pode ser +necessário para transmitir ideias adequadamente nas listas de discussão, +por isso recomenda-se que você verifique seus e-mails para garantir que +façam sentido em inglês antes de enviá-los. + + +Divida suas alterações +---------------------- + +A comunidade do kernel Linux não aceita de bom grado grandes blocos de +código jogados de uma só vez. As mudanças precisam ser devidamente +introduzidas, discutidas e divididas em porções minúsculas e individuais. +Isso é quase o exato oposto do que as empresas costumam fazer. Sua proposta +também deve ser introduzida muito cedo no processo de desenvolvimento, para +que você possa receber feedback sobre o que está fazendo. Isso também permite +que a comunidade sinta que você está trabalhando com eles, e não simplesmente +usando-os como um depósito para sua funcionalidade. No entanto, não envie +50 e-mails de uma só vez para uma lista de discussão; sua série de patches +deve ser menor que isso quase sempre. + +As razões para dividir as coisas são as seguintes: + +1) Patches pequenos aumentam a probabilidade de serem aplicados, pois não + exigem muito tempo ou esforço para verificar sua correção. Um patch de + 5 linhas pode ser aplicado por um mantenedor com apenas um olhar rápido. + No entanto, um patch de 500 linhas pode levar horas para ser revisado + (o tempo que leva é exponencialmente proporcional ao tamanho do patch, + ou algo assim). + + Patches pequenos também tornam muito fácil a depuração (debug) quando + algo dá errado. É muito mais fácil reverter patches um por um do que + dissecar um patch muito grande após ele ter sido aplicado (e quebrado algo). + +2) É importante não apenas enviar patches pequenos, mas também reescrever + e simplificar (ou simplesmente reordenar) os patches antes de submetê-los. + +Aqui está uma analogia do desenvolvedor do kernel Al Viro: + + *"Pense em um professor corrigindo o dever de casa de um aluno de + matemática. O professor não quer ver as tentativas e erros do aluno + antes de chegar à solução. Ele quer ver a resposta mais limpa e + elegante. Um bom aluno sabe disso e nunca enviaria seu trabalho + intermediário antes da solução final.* + + *O mesmo vale para o desenvolvimento do kernel. Os mantenedores e + revisores não querem ver o processo de pensamento por trás da solução + do problema que se está resolvendo. Eles querem ver uma solução + simples e elegante."* + +Pode ser desafiador manter o equilíbrio entre apresentar uma solução +elegante e trabalhar em conjunto com a comunidade discutindo seu trabalho +inacabado. Portanto, é bom entrar no processo cedo para obter feedback e +melhorar seu trabalho, mas também manter suas alterações em pequenos blocos +que possam ser aceitos, mesmo quando sua tarefa completa ainda não esteja +pronta para inclusão. + +Também entenda que não é aceitável enviar patches para inclusão que estejam +inacabados e que serão "consertados mais tarde". + + +Justifique sua alteração +------------------------ + +Além de dividir seus patches, é muito importante que você deixe a comunidade +Linux saber por que eles deveriam adicionar essa mudança. Novas +funcionalidades devem ser justificadas como necessárias e úteis. + + +Documente sua alteração +----------------------- + +Ao enviar seus patches, preste atenção especial ao que você diz no texto +do seu e-mail. Essas informações se tornarão as informações do ChangeLog +para o patch e serão preservadas para que todos vejam para sempre. Elas +devem descrever o patch completamente, contendo: + + - por que a mudança é necessária + - a abordagem geral de design no patch + - detalhes de implementação + - resultados de testes + +Para mais detalhes sobre como tudo isso deve ser, por favor, veja a seção +ChangeLog do documento: + + "O Patch Perfeito" + https://www.ozlabs.org/~akpm/stuff/tpp.txt + +Todas essas coisas às vezes são muito difíceis de fazer. Pode levar anos +para aperfeiçoar essas práticas (se é que é possível). É um processo +contínuo de melhoria que exige muita paciência e determinação. Mas não +desista, é possível. Muitos fizeram isso antes, e cada um teve que começar +exatamente onde você está agora. + +---------- + +Agradecimentos a Paolo Ciarrocchi, que permitiu que a seção "Processo de +Desenvolvimento" (https://lwn.net/Articles/94386/) fosse baseada em um +texto que ele escreveu, e a Randy Dunlap e Gerrit Huizenga por parte da +lista de coisas que você deve ou não dizer. Também agradecemos a 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 e Alex Shepard por suas revisões, comentários e contribuições. +Sem a ajuda deles, este documento não teria sido possível. + +Mantenedor: Greg Kroah-Hartman diff --git a/MAINTAINERS b/MAINTAINERS index 55af015174a5..202abb8a789d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20994,6 +20994,12 @@ S: Maintained F: drivers/pnp/ F: include/linux/pnp.h +PORTUGUESE (BRAZILIAN) TRANSLATION +M: Daniel Pereira +L: linux-doc@vger.kernel.org +S: Maintained +F: Documentation/translations/pt_BR/ + PORTWELL EC DRIVER M: Yen-Chi Huang L: platform-driver-x86@vger.kernel.org From c99fcb58501e1fbbfa5c9ee6f272db0623553f69 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 23 Feb 2026 14:29:30 -0700 Subject: [PATCH 002/162] docs: Fix an erroneous reference to sphinx.rst Just give the name of the file and let the automarkup stuff do its thing. Signed-off-by: Jonathan Corbet --- Documentation/process/changes.rst | 2 +- Documentation/translations/pt_BR/process/howto.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index 6b373e193548..f9f6f5c47882 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -391,7 +391,7 @@ Kernel documentation Sphinx ------ -Please see :ref:`sphinx_install` in :ref:`Documentation/doc-guide/sphinx.rst ` +Please see :ref:`sphinx_install` in Documentation/doc-guide/sphinx.rst for details about Sphinx requirements. rustdoc diff --git a/Documentation/translations/pt_BR/process/howto.rst b/Documentation/translations/pt_BR/process/howto.rst index 35bf633f21d6..56703010233c 100644 --- a/Documentation/translations/pt_BR/process/howto.rst +++ b/Documentation/translations/pt_BR/process/howto.rst @@ -1,6 +1,6 @@ .. SPDX-License-Identifier: GPL-2.0 -.. pt_process_howto: +.. _pt_process_howto: COMO FAZER o desenvolvimento do kernel Linux ============================================ From 8cf7280ccd01d777f5744d90381141a64f70fb5d Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Sun, 15 Feb 2026 15:12:48 +0200 Subject: [PATCH 003/162] Documentation/rtla: Add hwnoise to main page Add hwnoise to the command list and SEE ALSO section. The command list is ordered from low level to high level. Signed-off-by: Costa Shulyupin Signed-off-by: Jonathan Corbet Message-ID: <20260215131249.33437-1-costa.shul@redhat.com> --- Documentation/tools/rtla/rtla.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/tools/rtla/rtla.rst b/Documentation/tools/rtla/rtla.rst index 2a5fb7004ad4..6df1296b8cc1 100644 --- a/Documentation/tools/rtla/rtla.rst +++ b/Documentation/tools/rtla/rtla.rst @@ -21,6 +21,10 @@ results. COMMANDS ======== +**hwnoise** + + Detect and quantify hardware-related noise. + **osnoise** Gives information about the operating system noise (osnoise). @@ -39,7 +43,7 @@ For other options, see the man page for the corresponding command. SEE ALSO ======== -**rtla-osnoise**\(1), **rtla-timerlat**\(1) +**rtla-hwnoise**\(1), **rtla-osnoise**\(1), **rtla-timerlat**\(1) AUTHOR ====== From 46298375477b093204c1843b931c637621952ead Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 15 Feb 2026 22:07:39 -0800 Subject: [PATCH 004/162] linux-next: update maintainer info. Update the MAINTAINERS file and Documentation/process/2.Process.rst with the current linux-next maintainer information. Translations of 2.Process.rst should also be updated. Signed-off-by: Randy Dunlap Acked-by: Stephen Rothwell Acked-by: Mark Brown Signed-off-by: Jonathan Corbet Message-ID: <20260216060739.2791462-1-rdunlap@infradead.org> --- Documentation/process/2.Process.rst | 2 +- MAINTAINERS | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst index 57fa8cac58a6..77f3f80e7cd7 100644 --- a/Documentation/process/2.Process.rst +++ b/Documentation/process/2.Process.rst @@ -291,7 +291,7 @@ Use of the MMOTM tree is likely to be a frustrating experience, though; there is a definite chance that it will not even compile. The primary tree for next-cycle patch merging is linux-next, maintained by -Stephen Rothwell. The linux-next tree is, by design, a snapshot of what +Mark Brown. The linux-next tree is, by design, a snapshot of what the mainline is expected to look like after the next merge window closes. Linux-next trees are announced on the linux-kernel and linux-next mailing lists when they are assembled; they can be downloaded from: diff --git a/MAINTAINERS b/MAINTAINERS index 202abb8a789d..c05a72245049 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14748,7 +14748,6 @@ F: Documentation/memory-barriers.txt F: tools/memory-model/ LINUX-NEXT TREE -M: Stephen Rothwell M: Mark Brown L: linux-next@vger.kernel.org S: Supported From 95c0cd8bee59bc7ccc0d8c3008fec373ce8f0301 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 15 Feb 2026 22:37:29 -0800 Subject: [PATCH 005/162] docs: admin-guide: update tiny script for number of taint flags Account for 2 new taint flags being added by increasing the number of bits handled by the tiny show-tainted-flags example script. Fixes: 8eea4e744758 ("taint: Add TAINT_FWCTL") Fixes: 2852ca7fba9f ("panic: Taint kernel if tests are run") Signed-off-by: Randy Dunlap Reviewed-by: David Gow Signed-off-by: Jonathan Corbet Message-ID: <20260216063729.2832770-1-rdunlap@infradead.org> --- Documentation/admin-guide/tainted-kernels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst index ed1f8f1e86c5..9ead927a37c0 100644 --- a/Documentation/admin-guide/tainted-kernels.rst +++ b/Documentation/admin-guide/tainted-kernels.rst @@ -74,7 +74,7 @@ a particular type of taint. It's best to leave that to the aforementioned script, but if you need something quick you can use this shell command to check which bits are set:: - $ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done + $ for i in $(seq 20); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done Table for decoding tainted state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 1e9ae338eadda5796a57cc022359055ac3674bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Sabat=C3=A9=20Sol=C3=A0?= Date: Fri, 20 Feb 2026 00:40:40 +0100 Subject: [PATCH 006/162] documentation: update arch features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PA-RISC has perf-event support since commit 610cb23bcc75 ("parisc: Add initial kernel-side perf_event support"); and s390 has stackprotector support since commit f5730d44e05e ("s390: Add stackprotector support"). Signed-off-by: Miquel Sabaté Solà Signed-off-by: Jonathan Corbet Message-ID: <20260219234040.3260616-1-mssola@mssola.com> --- Documentation/features/perf/perf-regs/arch-support.txt | 2 +- Documentation/features/perf/perf-stackdump/arch-support.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt index 09431518b0e8..4c9a5a012075 100644 --- a/Documentation/features/perf/perf-regs/arch-support.txt +++ b/Documentation/features/perf/perf-regs/arch-support.txt @@ -18,7 +18,7 @@ | mips: | ok | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | ok | | s390: | ok | diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt index f9db4dd8ef79..dd362b5cb638 100644 --- a/Documentation/features/perf/perf-stackdump/arch-support.txt +++ b/Documentation/features/perf/perf-stackdump/arch-support.txt @@ -18,7 +18,7 @@ | mips: | ok | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | ok | | s390: | ok | From 32437123ee1c5a091adbf9531e3992c0ca0a97a1 Mon Sep 17 00:00:00 2001 From: Haowen Hu Date: Sat, 21 Feb 2026 00:01:26 +0800 Subject: [PATCH 007/162] docs/zh_TW: remove trailing space Remove one trailing space character. Signed-off-by: Haowen Hu Message-ID: <20260220160201.41149-2-srcres258@furdevs.cn> Signed-off-by: Jonathan Corbet --- Documentation/translations/zh_TW/admin-guide/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/translations/zh_TW/admin-guide/README.rst b/Documentation/translations/zh_TW/admin-guide/README.rst index c8b7ccfaa656..9be4915ae420 100644 --- a/Documentation/translations/zh_TW/admin-guide/README.rst +++ b/Documentation/translations/zh_TW/admin-guide/README.rst @@ -33,7 +33,7 @@ Linux內核6.x版本 雖然Linux最初是爲32位的x86 PC機(386或更高版本)開發的,但今天它也能運行在 (至少)Compaq Alpha AXP、Sun SPARC與UltraSPARC、Motorola 68000、PowerPC、 - PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel + PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel IA-64、DEC VAX、AMD x86-64 Xtensa和ARC架構上。 Linux很容易移植到大多數通用的32位或64位體系架構,只要它們有一個分頁內存管理 From fe539166e3f867c9761208d09a4f295bd9b7e910 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Fri, 20 Feb 2026 16:52:38 +0000 Subject: [PATCH 008/162] doc: early_userspace_support.rst: trivial fix: directory -> file Trivial fix. Signed-off-by: Askar Safin Signed-off-by: Jonathan Corbet Message-ID: <20260220165238.4162735-1-safinaskar@gmail.com> --- .../driver-api/early-userspace/early_userspace_support.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/early-userspace/early_userspace_support.rst b/Documentation/driver-api/early-userspace/early_userspace_support.rst index 61bdeac1bae5..60d1e1bc9413 100644 --- a/Documentation/driver-api/early-userspace/early_userspace_support.rst +++ b/Documentation/driver-api/early-userspace/early_userspace_support.rst @@ -73,7 +73,7 @@ usr/gen_initramfs.sh. This means that CONFIG_INITRAMFS_SOURCE can really be interpreted as any legal argument to gen_initramfs.sh. If a directory is specified as an argument then the contents are scanned, uid/gid translation is performed, and -usr/gen_init_cpio file directives are output. If a directory is +usr/gen_init_cpio file directives are output. If a file is specified as an argument to usr/gen_initramfs.sh then the contents of the file are simply copied to the output. All of the output directives from directory scanning and file contents copying are From 4058b259b9eb6371e3a10d0fd517820b5dfa2faa Mon Sep 17 00:00:00 2001 From: Pranav Kharche Date: Wed, 25 Feb 2026 18:59:51 +0530 Subject: [PATCH 009/162] docs: kernel-parameters: Fix repeated word in initramfs_options entry Remove the duplicate word 'for' in the initramfs_options description. Signed-off-by: Pranav Kharche Signed-off-by: Jonathan Corbet Message-ID: <20260225132951.36624-1-pranavkharche7@gmail.com> --- Documentation/admin-guide/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index cb850e5290c2..c3460c920f84 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6733,7 +6733,7 @@ Kernel parameters Default is 'on'. initramfs_options= [KNL] - Specify mount options for for the initramfs mount. + Specify mount options for the initramfs mount. rootfstype= [KNL] Set root filesystem type From 9a7bf1dc886f8c6becac4af7a0c2d17db2ae66b8 Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Tue, 24 Feb 2026 00:18:41 -0300 Subject: [PATCH 010/162] docs: pt_BR: translate process/changes.rst Translate the Documentation/process/changes.rst file into Portuguese. This document provides the list of minimum software requirements necessary to compile and run the Linux kernel. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260224031842.140732-1-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../translations/pt_BR/process/changes.rst | 576 ++++++++++++++++++ .../translations/pt_BR/process/howto.rst | 2 +- 3 files changed, 578 insertions(+), 1 deletion(-) create mode 100644 Documentation/translations/pt_BR/process/changes.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index 44fafb3c790a..55f9f377e201 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -67,3 +67,4 @@ kernel e sobre como ver seu trabalho integrado. :maxdepth: 1 Como começar + Requisitos mínimos diff --git a/Documentation/translations/pt_BR/process/changes.rst b/Documentation/translations/pt_BR/process/changes.rst new file mode 100644 index 000000000000..1964c1c93b34 --- /dev/null +++ b/Documentation/translations/pt_BR/process/changes.rst @@ -0,0 +1,576 @@ +.. SPDX-License-Identifier: GPL-2.0 + + + +Requisitos mínimos para compilar o Kernel +++++++++++++++++++++++++++++++++++++++++++ + +Introdução +=========== + +Este documento foi projetado para fornecer uma lista das versões mínimas +de software necessárias para executar a versão atual do kernel. + +Este documento é originalmente baseado no meu arquivo 'Changes' para os kernels +2.0.x e portanto, deve créditos às mesmas pessoas que aquele arquivo (Jared +Mauch, Axel Boldt, Alessandro Sigala e inúmeros outros usuários em toda a rede). + +Requisitos Mínimos Atuais +**************************** + +Atualize para pelo menos estas revisões de software antes de pensar que +encontrou um bug! Se não tiver certeza de qual versão está executando atualmente +, o comando sugerido deve lhe informar. + +Novamente, tenha em mente que esta lista pressupõe que você já possui um kernel +Linux em execução funcional. Além disso, nem todas as ferramentas são +necessárias em todos os sistemas; obviamente, se você não possui nenhum hardware +PC Card por exemplo, provavelmente não precisará se preocupar com o pcmciautils. + +====================== =============== ======================================== + Programa Versão mínima Comando para verificar a versão +====================== =============== ======================================== +GNU C 8.1 gcc --version +Clang/LLVM (optional) 15.0.0 clang --version +Rust (optional) 1.78.0 rustc --version +bindgen (optional) 0.65.1 bindgen --version +GNU make 4.0 make --version +bash 4.2 bash --version +binutils 2.30 ld -v +flex 2.5.35 flex --version +bison 2.0 bison --version +pahole 1.16 pahole --version +util-linux 2.10o mount --version +kmod 13 depmod -V +e2fsprogs 1.41.4 e2fsck -V +jfsutils 1.1.3 fsck.jfs -V +xfsprogs 2.6.0 xfs_db -V +squashfs-tools 4.0 mksquashfs -version +btrfs-progs 0.18 btrfs --version +pcmciautils 004 pccardctl -V +quota-tools 3.09 quota -V +PPP 2.4.0 pppd --version +nfs-utils 1.0.5 showmount --version +procps 3.2.0 ps --version +udev 081 udevd --version +grub 0.93 grub --version || grub-install --version +mcelog 0.6 mcelog --version +iptables 1.4.2 iptables -V +openssl & libcrypto 1.0.0 openssl version +bc 1.06.95 bc --version +Sphinx\ [#f1]_ 3.4.3 sphinx-build --version +GNU tar 1.28 tar --version +gtags (opcional) 6.6.5 gtags --version +mkimage (opcional) 2017.01 mkimage --version +Python 3.9.x python3 --version +GNU AWK (opcional) 5.1.0 gawk --version +====================== =============== ======================================== + +.. [#f1] O Sphinx é necessário apenas para gerar a documentação do Kernel. + +Compilação do Kernel +********************* + +GCC +--- + +Os requisitos da versão do gcc podem variar dependendo do tipo de CPU +do seu computador. + +Clang/LLVM (opcional) +--------------------- + +A versão formal mais recente do clang e dos utilitários LLVM (de acordo com +releases.llvm.org _) é suportada para a compilação +de kernels. Versões anteriores não têm funcionamento garantido, e poderemos +remover do kernel soluções de contorno (workarounds) que eram utilizadas para +suportar versões mais antigas. Por favor, veja a documentação adicional em: +ref:Building Linux with Clang/LLVM . + +Rust (opcional) +--------------- + +É necessária uma versão recente do compilador Rust. + +Por favor, consulte Documentation/rust/quick-start.rst para obter instruções +sobre como atender aos requisitos de compilação do suporte a Rust. Em +particular, o alvo (target) rustavailable do Makefile é útil para verificar por +que a cadeia de ferramentas (toolchain) Rust pode não estar sendo detectada. + +bindgen (opcional) +------------------ + +O ``bindgen`` é utilizado para gerar os vínculos (bindings) Rust para o lado C +do kernel. Ele depende da ``libclang``. + +Make +---- + +Você precisará do GNU make 4.0 ou superior para compilar o kernel. + +Bash +---- + +Alguns scripts bash são usados para a compilação do kernel. +É necessário o Bash 4.2 ou mais recente. + +Binutils +-------- + +O binutils 2.30 ou mais recente é necessário para compilar o kernel. + +pkg-config +---------- + +O sistema de compilação, a partir da versão 4.18, requer o pkg-config para +verificar as ferramentas kconfig instaladas e para determinar as configurações +de flags para uso em make {g,x}config. Anteriormente, o pkg-config já era +utilizado, mas não era verificado nem documentado. + +Flex +---- + +Desde o Linux 4.16, o sistema de compilação gera analisadores léxicos durante a +compilação. Isso requer o flex 2.5.35 ou superior. + + +Bison +----- + +Desde o Linux 4.16, o sistema de compilação gera analisadores sintáticos durante +a compilação. Isso requer o bison 2.0 ou superior + +pahole +------ + +Desde o Linux 5.2, se CONFIG_DEBUG_INFO_BTF estiver selecionado, o sistema de +compilação gera BTF (BPF Type Format) a partir do DWARF no vmlinux, e um pouco +depois para os módulos do kernel também. Isso requer o pahole v1.16 ou superior. + +Ele pode ser encontrado nos pacotes ``dwarves`` ou ``pahole`` das +distribuições, ou em https://fedorapeople.org/~acme/dwarves/. + +Perl +---- + +Você precisará do perl 5 e dos seguintes módulos: Getopt::Long, +Getopt::Std, File::Basename e File::Find para compilar o kernel. + +Python +------ + +Várias opções de configuração o exigem: ele é necessário para as configurações +padrão (defconfigs) de arm/arm64, CONFIG_LTO_CLANG, algumas configurações +opcionais de DRM, a ferramenta kernel-doc e a geração da documentação (Sphinx), +entre outros. + +BC +-- + +Você precisará do bc para compilar kernels 3.10 ou superior. + + +OpenSSL +------- + +A assinatura de módulos e a manipulação de certificados externos utilizam o +programa OpenSSL e a biblioteca de criptografia para realizar a criação de +chaves e a geração de assinaturas. + +Você precisará do openssl para compilar kernels 3.7 e superiores se a assinatura +de módulos estiver habilitada. Você também precisará dos pacotes de +desenvolvimento do openssl para compilar kernels 4.3 e superiores. + +Tar +--- + +O GNU tar é necessário caso você deseje habilitar o acesso aos cabeçalhos do +kernel via sysfs (CONFIG_IKHEADERS). + +gtags / GNU GLOBAL (optional) +----------------------------- + +A compilação do kernel requer o GNU GLOBAL versão 6.6.5 ou superior para gerar +arquivos de tags através de make gtags. Isso se deve ao uso da flag -C +(--directory) pelo gtags. + +mkimage +------- + +Esta ferramenta é utilizada ao gerar uma Flat Image Tree (FIT), comumente usada +em plataformas ARM. A ferramenta está disponível através do pacote u-boot-tools +ou pode ser compilada a partir do código-fonte do U-Boot. Veja as instruções em +https://docs.u-boot.org/en/latest/build/tools.html#building-tools-for-linux + +GNU AWK +------- + +O GNU AWK é necessário caso você deseje que a compilação do kernel gere dados de +intervalo de endereços para +módulos integrados (CONFIG_BUILTIN_MODULE_RANGES). + +Utilitários de sistema +*********************** + +Mudanças de arquitetura +------------------------ + +O DevFS tornou-se obsoleto em favor do udev +(https://www.kernel.org/pub/linux/utils/kernel/hotplug/) + +O suporte a UIDs de 32 bits já está implementado. Divirta-se! + +A documentação das funções do Linux está migrando para a documentação embutida +(inline), por meio de comentários com formatação especial próximos às suas +definições no código-fonte. Esses comentários podem ser combinados com arquivos +ReST no diretório Documentation/ para criar uma documentação enriquecida, que +pode então ser convertida para arquivos PostScript, HTML, LaTeX, ePUB e PDF. +Para converter do formato ReST para o formato de sua escolha,você precisará do +Sphinx. + +Util-linux +---------- + +Novas versões do util-linux oferecem suporte no fdisk para discos maiores, +suporte a novas opções para o mount, reconhecimento de mais tipos de partição e +outras funcionalidades interessantes. Você provavelmente vai querer atualizar. + +Ksymoops +-------- + +Se o impensável acontecer e o seu kernel sofrer um oops, você pode precisar da +ferramenta ksymoops para decodificá-lo, mas na maioria dos casos, não será +necessário. É geralmente preferível compilar o kernel com CONFIG_KALLSYMS para +que ele produza dumps legíveis que possam ser usados no estado em que se +encontram (isso também gera uma saída melhor do que a do ksymoops). +Se por algum motivo o seu kernel não for compilado com CONFIG_KALLSYMS e você +não tiver como recompilar e reproduzir o oops com essa opção, você ainda poderá +decodificá-lo com o ksymoops. + +Mkinitrd +-------- + +Estas mudanças no layout da árvore de arquivos /lib/modules também exigem que o +mkinitrd seja atualizado. + +E2fsprogs +--------- + +A versão mais recente do e2fsprogs corrige diversos bugs no fsck e no debugfs. +Obviamente, é uma boa ideia atualizar. + +JFSutils +-------- + +O pacote jfsutils contém os utilitários para o sistema de arquivos. Os seguintes +utilitários estão disponíveis: + +- ``fsck.jfs`` - inicia a reprodução (replay) do log de transações, além de + verificar e reparar uma partição formatada em JFS. + +- ``mkfs.jfs`` - cria uma partição formatada em JFS. + +- Para o seu arquivo changes.rst, a tradução técnica adequada é: + +Outros utilitários de sistema de arquivos também estão disponíveis neste pacote. + +Xfsprogs +-------- + +A versão mais recente do ``xfsprogs`` contém os utilitários ``mkfs.xfs``, +``xfs_db`` e ``xfs_repair``, entre outros, para o sistema de arquivos XFS. Ele é +independente de arquitetura e qualquer versão a partir da 2.0.0 deve funcionar +corretamente com esta versão do código do kernel XFS (recomenda-se a +versão 2.6.0 ou posterior, devido a algumas melhorias significativas). + +PCMCIAutils +----------- + +O PCMCIAutils substitui o pcmcia-cs. Ele configura corretamente os sockets +PCMCIA na inicialização do sistema e carrega os módulos apropriados para +dispositivos PCMCIA de 16 bits, caso o kernel esteja modularizado e o subsistema +de hotplug seja utilizado. + +Quota-tools +----------- + +O suporte a UIDs e GIDs de 32 bits é necessário caso você deseje utilizar o +formato de cota versão 2 mais recente. O quota-tools versão 3.07 e superiores +possuem esse suporte. Utilize a versão recomendada ou superior da tabela acima. + +Intel IA32 microcode +-------------------- + +Um driver foi adicionado para permitir a atualização do microcódigo Intel IA32, +acessível como um dispositivo de caracteres comum (misc). Se você não estiver +usando o udev, você poderá precisar de:: + + mkdir /dev/cpu + mknod /dev/cpu/microcode c 10 184 + chmod 0644 /dev/cpu/microcode + +Se você não estiver usando o udev, você poderá precisar executar os comandos +acima como root antes de poder usar isso. Você provavelmente também desejará +obter o utilitário de espaço de usuário ``microcode_ctl`` para utilizar em +conjunto com este driver. + +udev +---- + +O udev é uma aplicação de espaço de usuário para popular o diretório /dev +dinamicamente, apenas com entradas para dispositivos de fat presentes no +sistema. O udev substitui a funcionalidade básica do devfs, permitindo ao mesmo +tempo a nomeação persistente de dispositivos. + +FUSE +---- + +Necessita do libfuse 2.4.0 ou posterior. O mínimo absoluto é a versão 2.3.0, +mas as opções de montagem direct_io e kernel_cache não funcionarão. + +Redes +****** + +Mudanças gerais +---------------- + +Caso você tenha necessidades avançadas de configuração de rede, você deve +provavelmente considerar o uso das ferramentas de rede do iproute2. + +Filtro de Pacotes / NAT +------------------------ + +O código de filtragem de pacotes e NAT utiliza as mesmas ferramentas da série +anterior de kernels 2.4.x (iptables). Ele ainda inclui módulos de +retrocompatibilidade para o ipchains (estilo 2.2.x) e o ipfwadm (estilo 2.0.x). + +PPP +--- + +O driver PPP foi reestruturado para suportar multilink e permitir que opere +sobre diversas camadas de mídia. Se você utiliza PPP, atualize o pppd para, no +mínimo, a versão 2.4.0. + +Se você não estiver usando o udev, você deve possuir o arquivo de dispositivo +``/dev/ppp``, o qual pode ser criado por:: + + mknod /dev/ppp c 108 0 + +como root. + +NFS-utils +--------- + +Em kernels antigos (2.4 e anteriores), o servidor NFS precisava conhecer +qualquer cliente que pretendesse acessar arquivos via NFS. Essa informação era +fornecida ao kernel pelo mountd quando o cliente montava o sistema de arquivos, +ou pelo exportfs na inicialização do sistema. O exportfs obtinha informações +sobre clientes ativos a partir de /var/lib/nfs/rmtab. + +Esta abordagem é bastante frágil, pois depende da integridade do rmtab, o que +nem sempre é fácil, particularmente ao tentar implementar fail-over. Mesmo +quando o sistema está funcionando bem, o rmtab sofre com o acúmulo de muitas +entradas antigas que nunca são removidas. + +Com kernels modernos, temos a opção de fazer o kernel informar ao mountd quando +recebe uma requisição de um host desconhecido, permitindo que o mountd forneça +as informações de exportação apropriadas ao kernel. Isso remove a dependência do +rmtab e significa que o kernel só precisa conhecer os clientes ativos no +momento. + +Para habilitar esta nova funcionalidade, você precisa:: + + mount -t nfsd nfsd /proc/fs/nfsd + +antes de executar o exportfs ou o mountd. Recomenda-se que todos os serviços NFS +sejam protegidos da internet em geral por um firewall, sempre que possível. + +mcelog +------ + +Em kernels x86, o utilitário mcelog é necessário para processar e registrar +eventos de machine check quando opção CONFIG_X86_MCE está ativada. Eventos de +machine check são erros relatados pela CPU. O processamento desses eventos é +fortemente recomendado. + +Documentação do Kernel +*********************** + +Sphinx +------ + +Por favor, consulte Documentation/doc-guide/sphinx.rst para detalhes sobre os +requisitos do Sphinx. + +rustdoc +------- + +O rustdoc é utilizado para gerar a documentação para código Rust. Por favor, +consulte Documentation/rust/general-information.rst para mais informações. + +Obtendo software atualizado +============================ + +Compilação do kernel +********************** + +gcc +--- + +- + +Clang/LLVM +---------- + +- :ref:`Getting LLVM `. + +Rust +---- + +- Documentation/rust/quick-start.rst. + +bindgen +------- + +- Documentation/rust/quick-start.rst. + +Make +---- + +- + +Bash +---- + +- + +Binutils +-------- + +- + +Flex +---- + +- + +Bison +----- + +- + +OpenSSL +------- + +- + +System utilities +**************** + +Util-linux +---------- + +- + +Kmod +---- + +- +- + +Ksymoops +-------- + +- + +Mkinitrd +-------- + +- + +E2fsprogs +--------- + +- +- + +JFSutils +-------- + +- + +Xfsprogs +-------- + +- +- + +Pcmciautils +----------- + +- + +Quota-tools +----------- + +- + + +Intel P6 microcode +------------------ + +- + +udev +---- + +- + +FUSE +---- + +- + +mcelog +------ + +- + +Redes +****** + +PPP +--- + +- +- +- + +NFS-utils +--------- + +- +- + +Iptables +-------- + +- + +Ip-route2 +--------- + +- + +OProfile +-------- + +- + +Kernel documentation +******************** + +Sphinx +------ + +- diff --git a/Documentation/translations/pt_BR/process/howto.rst b/Documentation/translations/pt_BR/process/howto.rst index 56703010233c..bcedee7273fd 100644 --- a/Documentation/translations/pt_BR/process/howto.rst +++ b/Documentation/translations/pt_BR/process/howto.rst @@ -99,7 +99,7 @@ que são de leitura obrigatória: o que é necessário fazer para configurar e compilar o kernel. Pessoas que são novas no kernel devem começar por aqui. - :ref:`Documentation/process/changes.rst ` + :doc:`changes` Este arquivo fornece uma lista das versões mínimas de vários pacotes de software que são necessários para compilar e executar o kernel com sucesso. From b8c904a37608c9b2ef4ffa35f44a7e552454df51 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Mon, 23 Feb 2026 04:19:56 +0530 Subject: [PATCH 011/162] Doc: dev-tools: Added Gentoo in the Operating system list under Getting Coccinelle Adding Gentoo in the operating system list under "Getting Coccinelle". Signed-off-by: Bhaskar Chowdhury Signed-off-by: Jonathan Corbet Message-ID: <20260222225536.19196-1-unixbhaskar@gmail.com> --- Documentation/dev-tools/coccinelle.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst index c714780d458a..2b942e3c8049 100644 --- a/Documentation/dev-tools/coccinelle.rst +++ b/Documentation/dev-tools/coccinelle.rst @@ -29,6 +29,7 @@ of many distributions, e.g. : - Ubuntu - OpenSUSE - Arch Linux + - Gentoo - NetBSD - FreeBSD From ec6fd28baf61a6ae89e0208d7bc1447bc61b072e Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 26 Feb 2026 15:12:08 -0700 Subject: [PATCH 012/162] docs: remove unneeded maintainer_handbooks_main label Somehow people got into the habit of putting labels at the tops of documentation files, even when they are not used. It is better to just give the name of a file when linking to the whole thing; remove the label and update the references accordingly. Signed-off-by: Jonathan Corbet --- Documentation/process/maintainer-handbooks.rst | 2 -- Documentation/process/submitting-patches.rst | 2 +- Documentation/translations/ja_JP/process/submitting-patches.rst | 2 +- Documentation/translations/sp_SP/process/submitting-patches.rst | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Documentation/process/maintainer-handbooks.rst b/Documentation/process/maintainer-handbooks.rst index 976391cec528..3d72ad25fc6a 100644 --- a/Documentation/process/maintainer-handbooks.rst +++ b/Documentation/process/maintainer-handbooks.rst @@ -1,7 +1,5 @@ .. SPDX-License-Identifier: GPL-2.0 -.. _maintainer_handbooks_main: - Subsystem and maintainer tree specific development process notes ================================================================ diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index e69d19ad658f..c88e75bf0534 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -23,7 +23,7 @@ easier. Some subsystems and maintainer trees have additional information about their workflow and expectations, see -:ref:`Documentation/process/maintainer-handbooks.rst `. +Documentation/process/maintainer-handbooks.rst. Obtain a current source tree ---------------------------- diff --git a/Documentation/translations/ja_JP/process/submitting-patches.rst b/Documentation/translations/ja_JP/process/submitting-patches.rst index d61583399ef4..d229f4304cee 100644 --- a/Documentation/translations/ja_JP/process/submitting-patches.rst +++ b/Documentation/translations/ja_JP/process/submitting-patches.rst @@ -35,7 +35,7 @@ Documentation/devicetree/bindings/submitting-patches.rst を読んでくださ いくつかのサブシステムやメンテナツリーには、各々のワークフローや 期待事項に関する追加情報があります。次を参照してください: -:ref:`Documentation/process/maintainer-handbooks.rst `. +Documentation/process/maintainer-handbooks.rst. 現在のソースツリーを入手する ---------------------------- diff --git a/Documentation/translations/sp_SP/process/submitting-patches.rst b/Documentation/translations/sp_SP/process/submitting-patches.rst index ecb08b14c2c0..fc90c942f0e4 100644 --- a/Documentation/translations/sp_SP/process/submitting-patches.rst +++ b/Documentation/translations/sp_SP/process/submitting-patches.rst @@ -30,7 +30,7 @@ más sencilla. Algunos subsistemas y árboles de mantenimiento cuentan con información adicional sobre su flujo de trabajo y expectativas, consulte -:ref:`Documentation/process/maintainer-handbooks.rst `. +Documentation/process/maintainer-handbooks.rst. Obtenga el código fuente actual -------------------------------- From 4d2956e0094d9a7b04395185bc81467fa0ae1ccc Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 2 Mar 2026 14:51:42 +0100 Subject: [PATCH 013/162] Documentation/maintainer-tip: Fix grammar s/a empty newline/an empty newline/ Signed-off-by: Thorsten Blum Signed-off-by: Jonathan Corbet Message-ID: <20260302135141.3213-2-thorsten.blum@linux.dev> --- Documentation/process/maintainer-tip.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/process/maintainer-tip.rst b/Documentation/process/maintainer-tip.rst index 41d5855700cd..b2b14439be22 100644 --- a/Documentation/process/maintainer-tip.rst +++ b/Documentation/process/maintainer-tip.rst @@ -352,7 +352,7 @@ following tag ordering scheme: Changelog text starts here.... so the authorship is preserved. The 'From:' line has to be followed - by a empty newline. If that 'From:' line is missing, then the patch + by an empty newline. If that 'From:' line is missing, then the patch would be attributed to the person who sent (transported, handled) it. The 'From:' line is automatically removed when the patch is applied and does not show up in the final git changelog. It merely affects From c8975709eae716666b864316503e3acb88ffe06e Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Thu, 26 Feb 2026 19:58:48 -0300 Subject: [PATCH 014/162] docs: pt_BR: Add translation for maintainer-handbooks Translate the maintainer-handbooks.rst into Portuguese (Brazil) and update the main index to include it. This document provides a starting point for subsystem-specific development processes. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260226225849.268373-1-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../translations/pt_BR/process/maintainer-handbooks.rst | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 Documentation/translations/pt_BR/process/maintainer-handbooks.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index 55f9f377e201..de5c005f91d6 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -68,3 +68,4 @@ kernel e sobre como ver seu trabalho integrado. Como começar Requisitos mínimos + Manuais dos mantenedores diff --git a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst new file mode 100644 index 000000000000..eb650bc6006c --- /dev/null +++ b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Notas sobre o processo de desenvolvimento de subsistemas e mantenedores +======================================================================= + +O propósito deste documento é fornecer informações específicas de +subsistemas que são suplementares ao manual geral do processo de +desenvolvimento :ref:`Documentation/process `. From 8350d14725a459fba899d5642b7ced786424d33c Mon Sep 17 00:00:00 2001 From: Ariful Islam Shoikot Date: Thu, 26 Feb 2026 18:01:29 +0600 Subject: [PATCH 015/162] Documentation: process: backporting: fix missing subject Add the missing "it" in the sentence: "even though it could have been changed by other patches." This is a grammatical error in the Error handling section. Signed-off-by: Ariful Islam Shoikot Signed-off-by: Jonathan Corbet Message-ID: <20260226120129.18610-1-islamarifulshoikat@gmail.com> --- Documentation/process/backporting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/process/backporting.rst b/Documentation/process/backporting.rst index c42779fbcd33..0de9eacd46a7 100644 --- a/Documentation/process/backporting.rst +++ b/Documentation/process/backporting.rst @@ -432,7 +432,7 @@ The same goes for added ``return``, ``break``, and ``continue`` statements. Error handling is typically located at the bottom of the function, so it -may not be part of the conflict even though could have been changed by +may not be part of the conflict even though it could have been changed by other patches. A good way to ensure that you review the error paths is to always use From e7753827b9ba1827bf802e3268aea7716cddd6e6 Mon Sep 17 00:00:00 2001 From: Akiyoshi Kurita Date: Thu, 26 Feb 2026 00:47:06 +0900 Subject: [PATCH 016/162] docs: ja_JP: process: translate first half of 'Describe your changes' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translate the first half of the "Describe your changes" section in Documentation/translations/ja_JP/process/submitting-patches.rst. Replace "説明する" with "記述する" to match the distinction used in ja_JP/process/howto.rst, and adjust line wrapping to ~74 columns. Avoid cross-references for now by adding TODO notes to convert them to file-local references when the destinations are translated. Signed-off-by: Akiyoshi Kurita Acked-by: Akira Yokosawa Signed-off-by: Jonathan Corbet Message-ID: <20260225154706.5457-1-weibu@redadmin.org> --- .../ja_JP/process/submitting-patches.rst | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/Documentation/translations/ja_JP/process/submitting-patches.rst b/Documentation/translations/ja_JP/process/submitting-patches.rst index d229f4304cee..b89e63a1f65c 100644 --- a/Documentation/translations/ja_JP/process/submitting-patches.rst +++ b/Documentation/translations/ja_JP/process/submitting-patches.rst @@ -52,5 +52,47 @@ Documentation/process/maintainer-handbooks.rst. ツリーは MAINTAINERS ファイル内の **T:** エントリを参照して見つけてください。 そこに掲載されていない場合は、メンテナに問い合わせてください。 -変更内容を説明する +変更内容を記述する ------------------ + +問題を記述してください。あなたのパッチが 1 行のバグ修正であっても、 +5000 行の新機能であっても、それを行う動機となった根本的な問題が +必ずあるはずです。修正すべき価値のある問題が存在し、レビューアが +最初の段落以降を読む意味があることを納得させてください。 + +ユーザーから見える影響を記述してください。クラッシュやロックアップは +分かりやすいですが、すべてのバグがそこまで露骨とは限りません。 +たとえコードレビュー中に見つかった問題であっても、ユーザーに +どのような影響があり得るかを記述してください。 +Linux の多くの環境は、上流から特定のパッチだけを取り込む二次的な +安定版ツリーや、ベンダー/製品固有のツリーのカーネルで動いています。 +したがって、変更を下流へ適切に流す助けになる情報(発生条件、dmesg +の抜粋、クラッシュ内容、性能劣化、レイテンシのスパイク、 +ロックアップ等)があれば記載してください。 + +最適化とトレードオフを定量的に示してください。パフォーマンス、 +メモリ消費量、スタックフットプリント、バイナリサイズの改善を主張する +場合は、それを裏付ける数値を記載してください。 +また、目に見えないコストについても記述してください。最適化は通常 +無料ではなく、CPU・メモリ・可読性の間でのトレードオフになります。 +ヒューリスティクスの場合は、異なるワークロード間でのトレードオフに +なります。レビューアがコストとメリットを比較検討できるよう、 +最適化によって予想されるデメリットも記述してください。 + +問題を明確にできたら、実際にどのような対策を講じているかを技術的に +詳しく記述してください。レビューアがコードが意図したとおりに動作して +いるかを確認できるよう、変更内容を平易な言葉で書き下すことが重要です。 + +パッチ説明を Linux のソースコード管理システム ``git`` の +「コミットログ」としてそのまま取り込める形で書けば、メンテナは +助かります。詳細は原文の該当節を参照してください。 + +.. TODO: Convert to file-local cross-reference when the destination is + translated. + +1 つのパッチでは 1 つの問題だけを解決してください。記述が長くなり +始めたら、パッチを分割すべきサインです。詳細は原文の該当節を参照 +してください。 + +.. TODO: Convert to file-local cross-reference when the destination is + translated. From 6801cc493603b273698de501702ccc8751fb6689 Mon Sep 17 00:00:00 2001 From: Shubham Chakraborty Date: Tue, 24 Feb 2026 02:07:24 +0530 Subject: [PATCH 017/162] docs: sysctl: add documentation for crypto and debug Add documentation for the /proc/sys/crypto and /proc/sys/debug directories in the admin-guide. This includes tunables for FIPS mode (fips_enabled, fips_name, fips_version), exception-trace, and kprobes-optimization. The documentation is based on source code analysis and addresses stylistic feedback to keep it direct and concise. Tested-by: Randy Dunlap Signed-off-by: Shubham Chakraborty Signed-off-by: Jonathan Corbet Message-ID: <20260223203724.20874-1-chakrabortyshubham66@gmail.com> --- Documentation/admin-guide/sysctl/crypto.rst | 47 +++++++++++++++++++ Documentation/admin-guide/sysctl/debug.rst | 52 +++++++++++++++++++++ Documentation/admin-guide/sysctl/index.rst | 6 ++- 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 Documentation/admin-guide/sysctl/crypto.rst create mode 100644 Documentation/admin-guide/sysctl/debug.rst diff --git a/Documentation/admin-guide/sysctl/crypto.rst b/Documentation/admin-guide/sysctl/crypto.rst new file mode 100644 index 000000000000..b707bd314a64 --- /dev/null +++ b/Documentation/admin-guide/sysctl/crypto.rst @@ -0,0 +1,47 @@ +================= +/proc/sys/crypto/ +================= + +These files show up in ``/proc/sys/crypto/``, depending on the +kernel configuration: + +.. contents:: :local: + +fips_enabled +============ + +Read-only flag that indicates whether FIPS mode is enabled. + +- ``0``: FIPS mode is disabled (default). +- ``1``: FIPS mode is enabled. + +This value is set at boot time via the ``fips=1`` kernel command line +parameter. When enabled, the cryptographic API will restrict the use +of certain algorithms and perform self-tests to ensure compliance with +FIPS (Federal Information Processing Standards) requirements, such as +FIPS 140-2 and the newer FIPS 140-3, depending on the kernel +configuration and the module in use. + +fips_name +========= + +Read-only file that contains the name of the FIPS module currently in use. +The value is typically configured via the ``CONFIG_CRYPTO_FIPS_NAME`` +kernel configuration option. + +fips_version +============ + +Read-only file that contains the version string of the FIPS module. +If ``CONFIG_CRYPTO_FIPS_CUSTOM_VERSION`` is set, it uses the value from +``CONFIG_CRYPTO_FIPS_VERSION``. Otherwise, it defaults to the kernel +release version (``UTS_RELEASE``). + +Copyright (c) 2026, Shubham Chakraborty + +For general info and legal blurb, please look in +Documentation/admin-guide/sysctl/index.rst. + +.. See scripts/check-sysctl-docs to keep this up to date: +.. scripts/check-sysctl-docs -vtable="crypto" \ +.. $(git grep -l register_sysctl_) diff --git a/Documentation/admin-guide/sysctl/debug.rst b/Documentation/admin-guide/sysctl/debug.rst new file mode 100644 index 000000000000..506bd5e48594 --- /dev/null +++ b/Documentation/admin-guide/sysctl/debug.rst @@ -0,0 +1,52 @@ +================ +/proc/sys/debug/ +================ + +These files show up in ``/proc/sys/debug/``, depending on the +kernel configuration: + +.. contents:: :local: + +exception-trace +=============== + +This flag controls whether the kernel prints information about unhandled +signals (like segmentation faults) to the kernel log (``dmesg``). + +- ``0``: Unhandled signals are not traced. +- ``1``: Information about unhandled signals is printed. + +The default value is ``1`` on most architectures (like x86, MIPS, RISC-V), +but it is ``0`` on **arm64**. + +The actual information printed and the context provided varies +significantly depending on the CPU architecture. For example: + +- On **x86**, it typically prints the instruction pointer (IP), error + code, and address that caused a page fault. +- On **PowerPC**, it may print the next instruction pointer (NIP), + link register (LR), and other relevant registers. + +When enabled, this feature is often rate-limited to prevent the kernel +log from being flooded during a crash loop. + +kprobes-optimization +==================== + +This flag enables or disables the optimization of Kprobes on certain +architectures (like x86). + +- ``0``: Kprobes optimization is turned off. +- ``1``: Kprobes optimization is turned on (default). + +For more details on Kprobes and its optimization, please refer to +Documentation/trace/kprobes.rst. + +Copyright (c) 2026, Shubham Chakraborty + +For general info and legal blurb, please look in +Documentation/admin-guide/sysctl/index.rst. + +.. See scripts/check-sysctl-docs to keep this up to date: +.. scripts/check-sysctl-docs -vtable="debug" \ +.. $(git grep -l register_sysctl_) diff --git a/Documentation/admin-guide/sysctl/index.rst b/Documentation/admin-guide/sysctl/index.rst index 4dd2c9b5d752..e153c96119df 100644 --- a/Documentation/admin-guide/sysctl/index.rst +++ b/Documentation/admin-guide/sysctl/index.rst @@ -67,8 +67,8 @@ This documentation is about: =============== =============================================================== abi/ execution domains & personalities <$ARCH> tuning controls for various CPU architecture (e.g. csky, s390) -crypto/ -debug/ +crypto/ cryptographic subsystem +debug/ debugging features dev/ device specific information (e.g. dev/cdrom/info) fs/ specific filesystems filehandle, inode, dentry and quota tuning @@ -96,6 +96,8 @@ it :-) :maxdepth: 1 abi + crypto + debug fs kernel net From 2b144a30a407d29b7e6d24549f5316175115e788 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:44 +0100 Subject: [PATCH 018/162] docs: kdoc_re: add support for groups() Add an equivalent to re groups() method. This is useful on debug messages. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <20d1a9c77200e28cc2ff1d6122635c43f8ba6a71.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_re.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 0bf9e01cdc57..774dd747ecb0 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -106,6 +106,13 @@ class KernRe: return self.last_match.group(num) + def groups(self): + """ + Returns the group results of the last match + """ + + return self.last_match.groups() + class NestedMatch: """ From 8eb49357ffa229c9b65a002f655c1280dc09769a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:45 +0100 Subject: [PATCH 019/162] docs: kdoc_re: don't go past the end of a line The logic which checks if the line ends with ";" is currently broken: it may try to read past the buffer. Fix it by checking before trying to access line[pos]. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_re.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 774dd747ecb0..6c44fcce0415 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -269,7 +269,7 @@ class NestedMatch: out += new_sub # Drop end ';' if any - if line[pos] == ';': + if pos < len(line) and line[pos] == ';': pos += 1 cur_pos = pos From 77e6e17e9fc4cb4e59ad97de5453bb6f963a5fd4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:46 +0100 Subject: [PATCH 020/162] docs: kdoc_parser: move var transformers to the beginning Just like functions and structs had their transform variables placed at the beginning, move variable transforms to there as well. No functional changes. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <491b290252a308f381f88353a3bbe9e2bd1f6a62.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index ca00695b47b3..68a5aea9175d 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -192,6 +192,18 @@ function_xforms = [ (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), ] +# +# Transforms for variable prototypes +# +var_xforms = [ + (KernRe(r"__read_mostly"), ""), + (KernRe(r"__ro_after_init"), ""), + (KernRe(r"(?://.*)$"), ""), + (KernRe(r"(?:/\*.*\*/)"), ""), + (KernRe(r";$"), ""), + (KernRe(r"=.*"), ""), +] + # # Ancillary functions # @@ -972,15 +984,6 @@ class KernelDoc: ] OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?" - sub_prefixes = [ - (KernRe(r"__read_mostly"), ""), - (KernRe(r"__ro_after_init"), ""), - (KernRe(r"(?://.*)$"), ""), - (KernRe(r"(?:/\*.*\*/)"), ""), - (KernRe(r";$"), ""), - (KernRe(r"=.*"), ""), - ] - # # Store the full prototype before modifying it # @@ -1004,7 +1007,7 @@ class KernelDoc: # Drop comments and macros to have a pure C prototype # if not declaration_name: - for r, sub in sub_prefixes: + for r, sub in var_xforms: proto = r.sub(sub, proto) proto = proto.rstrip() From cca1bbdd72f72a3cf86d90fd6f326fd709ae931f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:47 +0100 Subject: [PATCH 021/162] docs: kdoc_parser: don't mangle with function defines Mangling with #defines is not nice, as we may end removing the macro names, preventing several macros from being properly documented. Also, on defines, we have something like: #define foo(a1, a2, a3, ...) \ /* some real implementation */ The prototype part (first line on this example) won't contain any macros, so no need to apply any regexes on it. With that, move the apply_transforms() logic to ensure that it will be called only on functions. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <8f9854c8ca1c794b6a3fe418f7adbc32aa68b432.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 68a5aea9175d..9643ffb7584a 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -163,7 +163,7 @@ struct_nested_prefixes = [ # # Transforms for function prototypes # -function_xforms = [ +function_xforms = [ (KernRe(r"^static +"), ""), (KernRe(r"^extern +"), ""), (KernRe(r"^asmlinkage +"), ""), @@ -1066,10 +1066,7 @@ class KernelDoc: found = func_macro = False return_type = '' decl_type = 'function' - # - # Apply the initial transformations. - # - prototype = apply_transforms(function_xforms, prototype) + # # If we have a macro, remove the "#define" at the front. # @@ -1088,6 +1085,11 @@ class KernelDoc: declaration_name = r.group(1) func_macro = True found = True + else: + # + # Apply the initial transformations. + # + prototype = apply_transforms(function_xforms, prototype) # Yes, this truly is vile. We are looking for: # 1. Return type (may be nothing if we're looking at a macro) From 4fd349f03dc51bc2f9cd2ea9f6309b0bc2b848ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:48 +0100 Subject: [PATCH 022/162] docs: kdoc_parser: fix variable regexes to work with size_t The regular expressions meant to pick variable types are too naive: they forgot that the type word may contain underlines. It also means that we need to change the regex which detects var attributes to handle "const". Co-developed-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <8230715239929cf9d475ab81ca1df7de65d82d06.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 9643ffb7584a..9c9443281c40 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -981,8 +981,9 @@ class KernelDoc: """ VAR_ATTRIBS = [ "extern", + "const", ] - OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?" + OPTIONAL_VAR_ATTR = r"^(?:\b(?:" +"|".join(VAR_ATTRIBS) +r")\b\s*)*" # # Store the full prototype before modifying it @@ -1018,14 +1019,14 @@ class KernelDoc: default_val = None - r= KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") + r= KernRe(OPTIONAL_VAR_ATTR + r"[\w_]*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") if r.match(proto): if not declaration_name: declaration_name = r.group(1) default_val = r.group(2) else: - r= KernRe(OPTIONAL_VAR_ATTR + r"(?:\w.*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") + r= KernRe(OPTIONAL_VAR_ATTR + r"(?:[\w_]*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") if r.match(proto): default_val = r.group(1) From 9bbf22b87d866fa1e6a1f9f6376d2ef458b6dcc7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:49 +0100 Subject: [PATCH 023/162] docs: kdoc_parser: fix the default_value logic for variables The indentation is wrong for the second regex, which causes problems on variables with defaults. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <681f18338abd6ae33cb9c15d72bb31a1cba75a9a.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 9c9443281c40..4bf55244870f 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -1027,9 +1027,9 @@ class KernelDoc: default_val = r.group(2) else: r= KernRe(OPTIONAL_VAR_ATTR + r"(?:[\w_]*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") - if r.match(proto): - default_val = r.group(1) + if r.match(proto): + default_val = r.group(1) if not declaration_name: self.emit_msg(ln,f"{proto}: can't parse variable") return From b7dc635459ad5b00f2d482406dbdca3291622ce2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:50 +0100 Subject: [PATCH 024/162] docs: kdoc_parser: don't exclude defaults from prototype If we do that, the defaults won't be parsed. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_parser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 4bf55244870f..39ff27d421eb 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -201,7 +201,6 @@ var_xforms = [ (KernRe(r"(?://.*)$"), ""), (KernRe(r"(?:/\*.*\*/)"), ""), (KernRe(r";$"), ""), - (KernRe(r"=.*"), ""), ] # From 6d9c2e9575b8630e17571a77eef8ade84a2a6344 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:51 +0100 Subject: [PATCH 025/162] docs: kdoc_parser: fix parser to support multi-word types The regular expression currently expects a single word for the type, but it may be something like "struct foo". Add support for it. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <544c73a9e670b6fef1828bf4f2ba0de7d29d8675.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 39ff27d421eb..22a820d33dc8 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -1018,14 +1018,14 @@ class KernelDoc: default_val = None - r= KernRe(OPTIONAL_VAR_ATTR + r"[\w_]*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") + r= KernRe(OPTIONAL_VAR_ATTR + r"\s*[\w_\s]*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") if r.match(proto): if not declaration_name: declaration_name = r.group(1) default_val = r.group(2) else: - r= KernRe(OPTIONAL_VAR_ATTR + r"(?:[\w_]*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") + r= KernRe(OPTIONAL_VAR_ATTR + r"(?:[\w_\s]*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") if r.match(proto): default_val = r.group(1) From 9bff5121fe22fdd0bb5bd6f744e136ec20bf7b95 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:52 +0100 Subject: [PATCH 026/162] docs: kdoc_parser: add support for LIST_HEAD Convert LIST_HEAD into struct list_head when handling its prototype. Signed-off-by: Mauro Carvalho Chehab Acked-by: Randy Dunlap Tested-by: Randy Dunlap Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <8bdfa6ba6002b0a73a83660f0ce7b40e30124552.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 22a820d33dc8..1df869061bf3 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -198,6 +198,7 @@ function_xforms = [ var_xforms = [ (KernRe(r"__read_mostly"), ""), (KernRe(r"__ro_after_init"), ""), + (KernRe(r"LIST_HEAD\(([\w_]+)\)"), r"struct list_head \1"), (KernRe(r"(?://.*)$"), ""), (KernRe(r"(?:/\*.*\*/)"), ""), (KernRe(r";$"), ""), From 97d4e70bc2c6f75911a9a5e1a75f2de13fde9b6b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 2 Mar 2026 17:40:53 +0100 Subject: [PATCH 027/162] docs: kdoc_parser: handle struct member macro VIRTIO_DECLARE_FEATURES(name) Parse the macro VIRTIO_DECLARE_FEATURES(name) and expand it to its definition. These prevents one build warning: WARNING: include/linux/virtio.h:188 struct member 'VIRTIO_DECLARE_FEATURES(features' not described in 'virtio_device' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <6f62e1f1210e74906fa50f4e937f66f54813661b.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 1df869061bf3..917e4528bfbf 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -150,6 +150,7 @@ struct_xforms = [ struct_args_pattern + r'\)', re.S), r'\1 \2[]'), (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), + (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), ] # # Regexes here are guaranteed to have the end delimiter matching From 95a9429cc6d31371575793ab7beb94bf3e7a2f92 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:54 +0100 Subject: [PATCH 028/162] docs: kdoc_re: better show KernRe() at documentation the __repr__() function is used by autodoc to document macro initialization. Add a better representation for them. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <80d27732368c14125c1b76048a70d8b4aee527ef.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_re.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 6c44fcce0415..664c04c8cc9f 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -52,7 +52,28 @@ class KernRe: return self.regex.pattern def __repr__(self): - return f're.compile("{self.regex.pattern}")' + """ + Returns a displayable version of the class init. + """ + + flag_map = { + re.IGNORECASE: "re.I", + re.MULTILINE: "re.M", + re.DOTALL: "re.S", + re.VERBOSE: "re.X", + } + + flags = [] + for flag, name in flag_map.items(): + if self.regex.flags & flag: + flags.append(name) + + flags_name = " | ".join(flags) + + if flags_name: + return f'KernRe("{self.regex.pattern}", {flags_name})' + else: + return f'KernRe("{self.regex.pattern}")' def __add__(self, other): """ From d842057c4a205084fb3036122c7426963f04e826 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:55 +0100 Subject: [PATCH 029/162] docs: kdoc_parser: move transform lists to a separate file Over the time, most of the changes at kernel-doc are related to maintaining a list of transforms to convert macros into pure C code. Place such transforms on a separate module, to cleanup the parser module. There is an advantage on that: QEMU also uses our own kernel-doc, but the xforms list there is different. By placing it on a separate module, we can minimize the differences and make it easier to keep QEMU in sync with Kernel upstream. No functional changes. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/tools/kdoc_parser.rst | 8 ++ tools/lib/python/kdoc/kdoc_files.py | 3 +- tools/lib/python/kdoc/kdoc_parser.py | 145 +----------------------- tools/lib/python/kdoc/xforms_lists.py | 153 ++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 141 deletions(-) create mode 100644 tools/lib/python/kdoc/xforms_lists.py diff --git a/Documentation/tools/kdoc_parser.rst b/Documentation/tools/kdoc_parser.rst index 03ee54a1b1cc..55b202173195 100644 --- a/Documentation/tools/kdoc_parser.rst +++ b/Documentation/tools/kdoc_parser.rst @@ -4,6 +4,14 @@ Kernel-doc parser stage ======================= +C replacement rules used by the parser +====================================== + +.. automodule:: lib.python.kdoc.xforms_lists + :members: + :show-inheritance: + :undoc-members: + File handler classes ==================== diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 022487ea2cc6..33618c6abec2 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -15,6 +15,7 @@ import os import re from kdoc.kdoc_parser import KernelDoc +from kdoc.xforms_lists import CTransforms from kdoc.kdoc_output import OutputFormat @@ -117,7 +118,7 @@ class KernelFiles(): if fname in self.files: return - doc = KernelDoc(self.config, fname) + doc = KernelDoc(self.config, fname, CTransforms()) export_table, entries = doc.parse_kdoc() self.export_table[fname] = export_table diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 917e4528bfbf..d7daf658e9d2 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -69,89 +69,6 @@ doc_begin_func = KernRe(str(doc_com) + # initial " * ' r'(?:[-:].*)?$', # description (not captured) cache = False) -# -# Here begins a long set of transformations to turn structure member prefixes -# and macro invocations into something we can parse and generate kdoc for. -# -struct_args_pattern = r'([^,)]+)' - -struct_xforms = [ - # Strip attributes - (KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=re.I | re.S, cache=False), ' '), - (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__packed\s*', re.S), ' '), - (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), - (KernRe(r'\s*__private', re.S), ' '), - (KernRe(r'\s*__rcu', re.S), ' '), - (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), - (KernRe(r'\s*____cacheline_aligned', re.S), ' '), - (KernRe(r'\s*__cacheline_group_(begin|end)\([^\)]+\);'), ''), - # - # Unwrap struct_group macros based on this definition: - # __struct_group(TAG, NAME, ATTRS, MEMBERS...) - # which has variants like: struct_group(NAME, MEMBERS...) - # Only MEMBERS arguments require documentation. - # - # Parsing them happens on two steps: - # - # 1. drop struct group arguments that aren't at MEMBERS, - # storing them as STRUCT_GROUP(MEMBERS) - # - # 2. remove STRUCT_GROUP() ancillary macro. - # - # The original logic used to remove STRUCT_GROUP() using an - # advanced regex: - # - # \bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*; - # - # with two patterns that are incompatible with - # Python re module, as it has: - # - # - a recursive pattern: (?1) - # - an atomic grouping: (?>...) - # - # I tried a simpler version: but it didn't work either: - # \bSTRUCT_GROUP\(([^\)]+)\)[^;]*; - # - # As it doesn't properly match the end parenthesis on some cases. - # - # So, a better solution was crafted: there's now a NestedMatch - # class that ensures that delimiters after a search are properly - # matched. So, the implementation to drop STRUCT_GROUP() will be - # handled in separate. - # - (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('), - (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GROUP('), - (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'struct \1 \2; STRUCT_GROUP('), - (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP('), - # - # Replace macros - # - # TODO: use NestedMatch for FOO($1, $2, ...) matches - # - # it is better to also move those to the NestedMatch logic, - # to ensure that parentheses will be properly matched. - # - (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), - r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), - (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), - r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), - (KernRe(r'DECLARE_BITMAP\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', - re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), - (KernRe(r'DECLARE_HASHTABLE\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', - re.S), r'unsigned long \1[1 << ((\2) - 1)]'), - (KernRe(r'DECLARE_KFIFO\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + - r',\s*' + struct_args_pattern + r'\)', re.S), r'\2 *\1'), - (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + struct_args_pattern + r',\s*' + - struct_args_pattern + r'\)', re.S), r'\2 *\1'), - (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + struct_args_pattern + r',\s*' + - struct_args_pattern + r'\)', re.S), r'\1 \2[]'), - (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), - (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), - (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), -] # # Regexes here are guaranteed to have the end delimiter matching # the start delimiter. Yet, right now, only one replace group @@ -161,62 +78,10 @@ struct_nested_prefixes = [ (re.compile(r'\bSTRUCT_GROUP\('), r'\1'), ] -# -# Transforms for function prototypes -# -function_xforms = [ - (KernRe(r"^static +"), ""), - (KernRe(r"^extern +"), ""), - (KernRe(r"^asmlinkage +"), ""), - (KernRe(r"^inline +"), ""), - (KernRe(r"^__inline__ +"), ""), - (KernRe(r"^__inline +"), ""), - (KernRe(r"^__always_inline +"), ""), - (KernRe(r"^noinline +"), ""), - (KernRe(r"^__FORTIFY_INLINE +"), ""), - (KernRe(r"__init +"), ""), - (KernRe(r"__init_or_module +"), ""), - (KernRe(r"__exit +"), ""), - (KernRe(r"__deprecated +"), ""), - (KernRe(r"__flatten +"), ""), - (KernRe(r"__meminit +"), ""), - (KernRe(r"__must_check +"), ""), - (KernRe(r"__weak +"), ""), - (KernRe(r"__sched +"), ""), - (KernRe(r"_noprof"), ""), - (KernRe(r"__always_unused *"), ""), - (KernRe(r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +"), ""), - (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""), - (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""), - (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"), - (KernRe(r"__attribute_const__ +"), ""), - (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), -] - -# -# Transforms for variable prototypes -# -var_xforms = [ - (KernRe(r"__read_mostly"), ""), - (KernRe(r"__ro_after_init"), ""), - (KernRe(r"LIST_HEAD\(([\w_]+)\)"), r"struct list_head \1"), - (KernRe(r"(?://.*)$"), ""), - (KernRe(r"(?:/\*.*\*/)"), ""), - (KernRe(r";$"), ""), -] - # # Ancillary functions # -def apply_transforms(xforms, text): - """ - Apply a set of transforms to a block of text. - """ - for search, subst in xforms: - text = search.sub(subst, text) - return text - multi_space = KernRe(r'\s\s+') def trim_whitespace(s): """ @@ -395,11 +260,12 @@ class KernelDoc: #: String to write when a parameter is not described. undescribed = "-- undescribed --" - def __init__(self, config, fname): + def __init__(self, config, fname, xforms): """Initialize internal variables""" self.fname = fname self.config = config + self.xforms = xforms # Initial state for the state machines self.state = state.NORMAL @@ -883,7 +749,7 @@ class KernelDoc: # Go through the list of members applying all of our transformations. # members = trim_private_members(members) - members = apply_transforms(struct_xforms, members) + members = self.xforms.apply("struct", members) nested = NestedMatch() for search, sub in struct_nested_prefixes: @@ -1009,8 +875,7 @@ class KernelDoc: # Drop comments and macros to have a pure C prototype # if not declaration_name: - for r, sub in var_xforms: - proto = r.sub(sub, proto) + proto = self.xforms.apply("var", proto) proto = proto.rstrip() @@ -1091,7 +956,7 @@ class KernelDoc: # # Apply the initial transformations. # - prototype = apply_transforms(function_xforms, prototype) + prototype = self.xforms.apply("func", prototype) # Yes, this truly is vile. We are looking for: # 1. Return type (may be nothing if we're looking at a macro) diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py new file mode 100644 index 000000000000..e6e0302e5dd0 --- /dev/null +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . + +import re + +from kdoc.kdoc_re import KernRe + +struct_args_pattern = r'([^,)]+)' + +class CTransforms: + """ + Data class containing a long set of transformations to turn + structure member prefixes, and macro invocations and variables + into something we can parse and generate kdoc for. + """ + + #: Transforms for structs and unions. + struct_xforms = [ + # Strip attributes + (KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=re.I | re.S, cache=False), ' '), + (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__packed\s*', re.S), ' '), + (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), + (KernRe(r'\s*__private', re.S), ' '), + (KernRe(r'\s*__rcu', re.S), ' '), + (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), + (KernRe(r'\s*____cacheline_aligned', re.S), ' '), + (KernRe(r'\s*__cacheline_group_(begin|end)\([^\)]+\);'), ''), + # + # Unwrap struct_group macros based on this definition: + # __struct_group(TAG, NAME, ATTRS, MEMBERS...) + # which has variants like: struct_group(NAME, MEMBERS...) + # Only MEMBERS arguments require documentation. + # + # Parsing them happens on two steps: + # + # 1. drop struct group arguments that aren't at MEMBERS, + # storing them as STRUCT_GROUP(MEMBERS) + # + # 2. remove STRUCT_GROUP() ancillary macro. + # + # The original logic used to remove STRUCT_GROUP() using an + # advanced regex: + # + # \bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*; + # + # with two patterns that are incompatible with + # Python re module, as it has: + # + # - a recursive pattern: (?1) + # - an atomic grouping: (?>...) + # + # I tried a simpler version: but it didn't work either: + # \bSTRUCT_GROUP\(([^\)]+)\)[^;]*; + # + # As it doesn't properly match the end parenthesis on some cases. + # + # So, a better solution was crafted: there's now a NestedMatch + # class that ensures that delimiters after a search are properly + # matched. So, the implementation to drop STRUCT_GROUP() will be + # handled in separate. + # + (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('), + (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GROUP('), + (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'struct \1 \2; STRUCT_GROUP('), + (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP('), + # + # Replace macros + # + # TODO: use NestedMatch for FOO($1, $2, ...) matches + # + # it is better to also move those to the NestedMatch logic, + # to ensure that parentheses will be properly matched. + # + (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), + r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), + (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), + r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), + (KernRe(r'DECLARE_BITMAP\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', + re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), + (KernRe(r'DECLARE_HASHTABLE\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', + re.S), r'unsigned long \1[1 << ((\2) - 1)]'), + (KernRe(r'DECLARE_KFIFO\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + + r',\s*' + struct_args_pattern + r'\)', re.S), r'\2 *\1'), + (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + struct_args_pattern + r',\s*' + + struct_args_pattern + r'\)', re.S), r'\2 *\1'), + (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + struct_args_pattern + r',\s*' + + struct_args_pattern + r'\)', re.S), r'\1 \2[]'), + (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), + (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), + (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), + ] + + #: Transforms for function prototypes. + function_xforms = [ + (KernRe(r"^static +"), ""), + (KernRe(r"^extern +"), ""), + (KernRe(r"^asmlinkage +"), ""), + (KernRe(r"^inline +"), ""), + (KernRe(r"^__inline__ +"), ""), + (KernRe(r"^__inline +"), ""), + (KernRe(r"^__always_inline +"), ""), + (KernRe(r"^noinline +"), ""), + (KernRe(r"^__FORTIFY_INLINE +"), ""), + (KernRe(r"__init +"), ""), + (KernRe(r"__init_or_module +"), ""), + (KernRe(r"__exit +"), ""), + (KernRe(r"__deprecated +"), ""), + (KernRe(r"__flatten +"), ""), + (KernRe(r"__meminit +"), ""), + (KernRe(r"__must_check +"), ""), + (KernRe(r"__weak +"), ""), + (KernRe(r"__sched +"), ""), + (KernRe(r"_noprof"), ""), + (KernRe(r"__always_unused *"), ""), + (KernRe(r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +"), ""), + (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""), + (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""), + (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"), + (KernRe(r"__attribute_const__ +"), ""), + (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), + ] + + #: Transforms for variable prototypes. + var_xforms = [ + (KernRe(r"__read_mostly"), ""), + (KernRe(r"__ro_after_init"), ""), + (KernRe(r"LIST_HEAD\(([\w_]+)\)"), r"struct list_head \1"), + (KernRe(r"(?://.*)$"), ""), + (KernRe(r"(?:/\*.*\*/)"), ""), + (KernRe(r";$"), ""), + ] + + #: Transforms main dictionary used at apply_transforms(). + xforms = { + "struct": struct_xforms, + "func": function_xforms, + "var": var_xforms, + } + + def apply(self, xforms_type, text): + """ + Apply a set of transforms to a block of text. + """ + if xforms_type not in self.xforms: + return text + + for search, subst in self.xforms[xforms_type]: + text = search.sub(subst, text) + return text From 4ff59bdd93f0e80b5014977502d082c778f96304 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 2 Mar 2026 17:40:56 +0100 Subject: [PATCH 030/162] docs: xforms_lists: ignore context analysis and lock attributes Drop context analysis and lock (tracking) attributes to avoid kernel-doc warnings. There are now lots of warnings like these: Documentation/core-api/kref:328: ../include/linux/kref.h:72: WARNING: Invalid C declaration: Expected end of definition. [error at 96] int kref_put_mutex (struct kref *kref, void (*release)(struct kref *kref), struct mutex *mutex) __cond_acquires(true# mutex) ------------------------------------------------------------------------------------------------^ Documentation/core-api/kref:328: ../include/linux/kref.h:94: WARNING: Invalid C declaration: Expected end of definition. [error at 92] int kref_put_lock (struct kref *kref, void (*release)(struct kref *kref), spinlock_t *lock) __cond_acquires(true# lock) --------------------------------------------------------------------------------------------^ The regex is suggested by Mauro; mine was too greedy. Thanks. Updated context analysis and lock macros list provided by PeterZ. Thanks. [mchehab: modified to be applied after xforms_lists split] Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/all/20260107161548.45530e1c@canb.auug.org.au/ Signed-off-by: Randy Dunlap Reviewed-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <3c7fdfc364a8920f92530b47bdbf4bb29a40371f.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 10 ++++++++++ tools/lib/python/kdoc/xforms_lists.py | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index d7daf658e9d2..503a18212747 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -75,6 +75,16 @@ doc_begin_func = KernRe(str(doc_com) + # initial " * ' # is allowed. # struct_nested_prefixes = [ + (re.compile(r"__cond_acquires\s*\("), ""), + (re.compile(r"__cond_releases\s*\("), ""), + (re.compile(r"__acquires\s*\("), ""), + (re.compile(r"__releases\s*\("), ""), + (re.compile(r"__must_hold\s*\("), ""), + (re.compile(r"__must_not_hold\s*\("), ""), + (re.compile(r"__must_hold_shared\s*\("), ""), + (re.compile(r"__cond_acquires_shared\s*\("), ""), + (re.compile(r"__acquires_shared\s*\("), ""), + (re.compile(r"__releases_shared\s*\("), ""), (re.compile(r'\bSTRUCT_GROUP\('), r'\1'), ] diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index e6e0302e5dd0..1bda7c4634c3 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -22,6 +22,8 @@ class CTransforms: (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__guarded_by\s*\([^\)]*\)', re.S), ' '), + (KernRe(r'\s*__pt_guarded_by\s*\([^\)]*\)', re.S), ' '), (KernRe(r'\s*__packed\s*', re.S), ' '), (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), (KernRe(r'\s*__private', re.S), ' '), @@ -120,6 +122,7 @@ class CTransforms: (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""), (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""), (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"), + (KernRe(r"__no_context_analysis\s*"), ""), (KernRe(r"__attribute_const__ +"), ""), (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), ] @@ -128,6 +131,8 @@ class CTransforms: var_xforms = [ (KernRe(r"__read_mostly"), ""), (KernRe(r"__ro_after_init"), ""), + (KernRe(r'\s*__guarded_by\s*\([^\)]*\)', re.S), ""), + (KernRe(r'\s*__pt_guarded_by\s*\([^\)]*\)', re.S), ""), (KernRe(r"LIST_HEAD\(([\w_]+)\)"), r"struct list_head \1"), (KernRe(r"(?://.*)$"), ""), (KernRe(r"(?:/\*.*\*/)"), ""), From 134468b0e2043efec4bd25dc6bcef238358a8111 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:57 +0100 Subject: [PATCH 031/162] docs: kdoc_re: handle strings and escape chars on NextMatch The logic inside NestedMatch currently doesn't consider that function arguments may have chars and strings, which may eventually contain delimiters. Add logic to handle strings and escape characters on them. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_re.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 664c04c8cc9f..0a7f12616f9f 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -216,6 +216,8 @@ class NestedMatch: for match_re in regex.finditer(line): start = match_re.start() offset = match_re.end() + string_char = None + escape = False d = line[offset - 1] if d not in self.DELIMITER_PAIRS: @@ -229,6 +231,22 @@ class NestedMatch: d = line[pos] + if escape: + escape = False + continue + + if string_char: + if d == '\\': + escape = True + elif d == string_char: + string_char = None + + continue + + if d in ('"', "'"): + string_char = d + continue + if d in self.DELIMITER_PAIRS: end = self.DELIMITER_PAIRS[d] From 962bdc440df58008e0319d6cbe08c4ca1193c112 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:58 +0100 Subject: [PATCH 032/162] docs: kdoc_re: don't recompile NestedMatch regex every time Store delimiters and its regex-compiled version as const vars. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <0cf2b72d4785aa8b727188b56688ff442d1c65ce.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_re.py | 35 ++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 0a7f12616f9f..00afa5bccd6d 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -99,6 +99,13 @@ class KernRe: self.last_match = self.regex.search(string) return self.last_match + def finditer(self, string): + """ + Alias to re.finditer. + """ + + return self.regex.finditer(string) + def findall(self, string): """ Alias to re.findall. @@ -134,6 +141,16 @@ class KernRe: return self.last_match.groups() +#: Nested delimited pairs (brackets and parenthesis) +DELIMITER_PAIRS = { + '{': '}', + '(': ')', + '[': ']', +} + +#: compiled delimiters +RE_DELIM = KernRe(r'[\{\}\[\]\(\)]') + class NestedMatch: """ @@ -183,14 +200,6 @@ class NestedMatch: # # FOO(arg1, arg2, arg3) - DELIMITER_PAIRS = { - '{': '}', - '(': ')', - '[': ']', - } - - RE_DELIM = re.compile(r'[\{\}\[\]\(\)]') - def _search(self, regex, line): """ Finds paired blocks for a regex that ends with a delimiter. @@ -220,13 +229,13 @@ class NestedMatch: escape = False d = line[offset - 1] - if d not in self.DELIMITER_PAIRS: + if d not in DELIMITER_PAIRS: continue - end = self.DELIMITER_PAIRS[d] + end = DELIMITER_PAIRS[d] stack.append(end) - for match in self.RE_DELIM.finditer(line[offset:]): + for match in RE_DELIM.finditer(line[offset:]): pos = match.start() + offset d = line[pos] @@ -247,8 +256,8 @@ class NestedMatch: string_char = d continue - if d in self.DELIMITER_PAIRS: - end = self.DELIMITER_PAIRS[d] + if d in DELIMITER_PAIRS: + end = DELIMITER_PAIRS[d] stack.append(end) continue From 34503b5fd10d8c7f1b1f4fecb6aae826fcf79424 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:40:59 +0100 Subject: [PATCH 033/162] docs: kdoc_re: Change NestedMath args replacement to \0 Future patches will allow parsing each argument instead of the hole set. Prepare for it by changing the replace all args from \1 to \0. No functional changes. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <46e383118be9d9e432e3814fe819ebb12261d7b4.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 2 +- tools/lib/python/kdoc/kdoc_re.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 503a18212747..0f90c16cb51a 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -85,7 +85,7 @@ struct_nested_prefixes = [ (re.compile(r"__cond_acquires_shared\s*\("), ""), (re.compile(r"__acquires_shared\s*\("), ""), (re.compile(r"__releases_shared\s*\("), ""), - (re.compile(r'\bSTRUCT_GROUP\('), r'\1'), + (re.compile(r'\bSTRUCT_GROUP\('), r'\0'), ] # diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 00afa5bccd6d..ea4f6f3d9e42 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -188,7 +188,7 @@ class NestedMatch: # except that the content inside the match group is delimiter-aligned. # # The content inside parentheses is converted into a single replace - # group (e.g. r`\1'). + # group (e.g. r`\0'). # # It would be nice to change such definition to support multiple # match groups, allowing a regex equivalent to: @@ -291,7 +291,7 @@ class NestedMatch: if the sub argument contains:: - r'\1' + r'\0' it will work just like re: it places there the matched paired data with the delimiter stripped. @@ -310,9 +310,9 @@ class NestedMatch: # Value, ignoring start/end delimiters value = line[end:pos - 1] - # replaces \1 at the sub string, if \1 is used there + # replaces \0 at the sub string, if \0 is used there new_sub = sub - new_sub = new_sub.replace(r'\1', value) + new_sub = new_sub.replace(r'\0', value) out += new_sub From fc44c0a0b2a72f2e9331063a311a548634ae18af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:41:00 +0100 Subject: [PATCH 034/162] docs: kdoc_re: make NestedMatch use KernRe Instead of using re_compile, let's create the class with the regex and use KernRe to keep it cached. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_parser.py | 25 ++++++++++++------------- tools/lib/python/kdoc/kdoc_re.py | 24 +++++++++++++++++------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 0f90c16cb51a..cd9857906a2b 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -75,17 +75,17 @@ doc_begin_func = KernRe(str(doc_com) + # initial " * ' # is allowed. # struct_nested_prefixes = [ - (re.compile(r"__cond_acquires\s*\("), ""), - (re.compile(r"__cond_releases\s*\("), ""), - (re.compile(r"__acquires\s*\("), ""), - (re.compile(r"__releases\s*\("), ""), - (re.compile(r"__must_hold\s*\("), ""), - (re.compile(r"__must_not_hold\s*\("), ""), - (re.compile(r"__must_hold_shared\s*\("), ""), - (re.compile(r"__cond_acquires_shared\s*\("), ""), - (re.compile(r"__acquires_shared\s*\("), ""), - (re.compile(r"__releases_shared\s*\("), ""), - (re.compile(r'\bSTRUCT_GROUP\('), r'\0'), + (NestedMatch(r"__cond_acquires\s*\("), ""), + (NestedMatch(r"__cond_releases\s*\("), ""), + (NestedMatch(r"__acquires\s*\("), ""), + (NestedMatch(r"__releases\s*\("), ""), + (NestedMatch(r"__must_hold\s*\("), ""), + (NestedMatch(r"__must_not_hold\s*\("), ""), + (NestedMatch(r"__must_hold_shared\s*\("), ""), + (NestedMatch(r"__cond_acquires_shared\s*\("), ""), + (NestedMatch(r"__acquires_shared\s*\("), ""), + (NestedMatch(r"__releases_shared\s*\("), ""), + (NestedMatch(r'\bSTRUCT_GROUP\('), r'\0'), ] # @@ -761,9 +761,8 @@ class KernelDoc: members = trim_private_members(members) members = self.xforms.apply("struct", members) - nested = NestedMatch() for search, sub in struct_nested_prefixes: - members = nested.sub(search, sub, members) + members = search.sub(search, sub, members) # # Deal with embedded struct and union members, and drop enums entirely. # diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index ea4f6f3d9e42..085b89a4547c 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -200,7 +200,10 @@ class NestedMatch: # # FOO(arg1, arg2, arg3) - def _search(self, regex, line): + def __init__(self, regex): + self.regex = KernRe(regex) + + def _search(self, line): """ Finds paired blocks for a regex that ends with a delimiter. @@ -222,7 +225,7 @@ class NestedMatch: stack = [] - for match_re in regex.finditer(line): + for match_re in self.regex.finditer(line): start = match_re.start() offset = match_re.end() string_char = None @@ -270,7 +273,7 @@ class NestedMatch: yield start, offset, pos + 1 break - def search(self, regex, line): + def search(self, line): """ This is similar to re.search: @@ -278,12 +281,12 @@ class NestedMatch: returning occurrences only if all delimiters are paired. """ - for t in self._search(regex, line): + for t in self._search(line): yield line[t[0]:t[2]] - def sub(self, regex, sub, line, count=0): - r""" + def sub(self, sub, line, count=0): + """ This is similar to re.sub: It matches a regex that it is followed by a delimiter, @@ -304,7 +307,7 @@ class NestedMatch: cur_pos = 0 n = 0 - for start, end, pos in self._search(regex, line): + for start, end, pos in self._search(line): out += line[cur_pos:start] # Value, ignoring start/end delimiters @@ -331,3 +334,10 @@ class NestedMatch: out += line[cur_pos:l] return out + + def __repr__(self): + """ + Returns a displayable version of the class init. + """ + + return f'NestedMatch("{self.regex.regex.pattern}")' From 85c2a51357f720fabfb6fa8d2551d87a94e797cb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2026 17:41:01 +0100 Subject: [PATCH 035/162] docs: kdoc_parser: move nested match transforms to xforms_lists.py As NestedMatch now has a sub method and a declaration close to what KernRe does, we can move the rules to xforms_lists and simplify kdoc_parser a little bit. No functional changes. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <762ce2a58ff024c1b0b6f6a6e05020d1415b8308.1772469446.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 21 --------------------- tools/lib/python/kdoc/xforms_lists.py | 14 +++++++++++++- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index cd9857906a2b..edf70ba139a5 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -69,25 +69,6 @@ doc_begin_func = KernRe(str(doc_com) + # initial " * ' r'(?:[-:].*)?$', # description (not captured) cache = False) -# -# Regexes here are guaranteed to have the end delimiter matching -# the start delimiter. Yet, right now, only one replace group -# is allowed. -# -struct_nested_prefixes = [ - (NestedMatch(r"__cond_acquires\s*\("), ""), - (NestedMatch(r"__cond_releases\s*\("), ""), - (NestedMatch(r"__acquires\s*\("), ""), - (NestedMatch(r"__releases\s*\("), ""), - (NestedMatch(r"__must_hold\s*\("), ""), - (NestedMatch(r"__must_not_hold\s*\("), ""), - (NestedMatch(r"__must_hold_shared\s*\("), ""), - (NestedMatch(r"__cond_acquires_shared\s*\("), ""), - (NestedMatch(r"__acquires_shared\s*\("), ""), - (NestedMatch(r"__releases_shared\s*\("), ""), - (NestedMatch(r'\bSTRUCT_GROUP\('), r'\0'), -] - # # Ancillary functions # @@ -761,8 +742,6 @@ class KernelDoc: members = trim_private_members(members) members = self.xforms.apply("struct", members) - for search, sub in struct_nested_prefixes: - members = search.sub(search, sub, members) # # Deal with embedded struct and union members, and drop enums entirely. # diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index 1bda7c4634c3..c07cbe1e6349 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -4,7 +4,7 @@ import re -from kdoc.kdoc_re import KernRe +from kdoc.kdoc_re import KernRe, NestedMatch struct_args_pattern = r'([^,)]+)' @@ -94,6 +94,18 @@ class CTransforms: (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), + + (NestedMatch(r"__cond_acquires\s*\("), ""), + (NestedMatch(r"__cond_releases\s*\("), ""), + (NestedMatch(r"__acquires\s*\("), ""), + (NestedMatch(r"__releases\s*\("), ""), + (NestedMatch(r"__must_hold\s*\("), ""), + (NestedMatch(r"__must_not_hold\s*\("), ""), + (NestedMatch(r"__must_hold_shared\s*\("), ""), + (NestedMatch(r"__cond_acquires_shared\s*\("), ""), + (NestedMatch(r"__acquires_shared\s*\("), ""), + (NestedMatch(r"__releases_shared\s*\("), ""), + (NestedMatch(r'\bSTRUCT_GROUP\('), r'\0'), ] #: Transforms for function prototypes. From 2b8060418dffaa4fcd9173dd5830a763a4b32e99 Mon Sep 17 00:00:00 2001 From: Matteo Martelli Date: Mon, 23 Feb 2026 14:05:31 +0100 Subject: [PATCH 036/162] sched_deadline, docs: fix cpuset example for cgroupv2 Documenation/scheduler/sched-deadline.rst provides two examples for how to setup cgroup and cpuset for deadline tasks: one for cgroup v1 and one cgroup v2. The code block in the latter is not properly html rendered as the :: marker is missing. Add the :: marker before the code block for the cgroup v2 example to fix html rendering. Also make the example description more explicit for better clarity. Fixes: 0116765035eb ("sched_deadline, docs: add affinity setting with cgroup2 cpuset controller") Signed-off-by: Matteo Martelli Signed-off-by: Jonathan Corbet Message-ID: <20260223-docs-sched-deadline-fix-example-v1-1-8d0bedc2bc6f@codethink.co.uk> --- Documentation/scheduler/sched-deadline.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/scheduler/sched-deadline.rst b/Documentation/scheduler/sched-deadline.rst index ec543a12f848..d23e4afe1a9a 100644 --- a/Documentation/scheduler/sched-deadline.rst +++ b/Documentation/scheduler/sched-deadline.rst @@ -700,7 +700,8 @@ Deadline Task Scheduling 5.2 Using cgroup v2 cpuset controller ------------------------------------- - Assuming the cgroup v2 root is mounted at ``/sys/fs/cgroup``. + Assuming the cgroup v2 root is mounted at ``/sys/fs/cgroup``, an example of a + simple configuration (pin a -deadline task to CPU0) follows:: cd /sys/fs/cgroup echo '+cpuset' > cgroup.subtree_control From d20e945e9fe631381dc426eaeaddeed0eb47935a Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Mon, 23 Feb 2026 09:20:47 +0100 Subject: [PATCH 037/162] docs: handling-regressions: add, trim, and sort quotes from Linus Add additional quotes from Linus while trimming the existing ones and sorting them all into categories. That makes it easier for new developers and maintainers to look up how Linus expects certain situations wrt regressions to be handled. The earlier sections in the document already explain this, but those parts are often questioned -- or not considered authoritative at all and plainly ignored. Having it straight from the horse's mouth helps get everyone on the same page, even if that makes the document quite a bit longer (the raw line count of this section doubles, but the number of characters increases by nearly 50%). In return, this covers a lot more aspects and, due to the sub-headings, is easier to navigate. In contrast to the more neutral description in the early sections of the document, this also provides a better insight into how serious Linus is about the "no regressions" rule and how he wants it to be interpreted in practice; this makes it easier for new developers and maintainers to understand things and prevent run-ins with higher-level maintainers. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: --- .../process/handling-regressions.rst | 695 ++++++++++++------ 1 file changed, 463 insertions(+), 232 deletions(-) diff --git a/Documentation/process/handling-regressions.rst b/Documentation/process/handling-regressions.rst index 1f5ab49c48a4..c71b5d403f0c 100644 --- a/Documentation/process/handling-regressions.rst +++ b/Documentation/process/handling-regressions.rst @@ -461,325 +461,556 @@ which both cover more details than the above section. Quotes from Linus about regression ---------------------------------- -Find below a few real life examples of how Linus Torvalds expects regressions to -be handled: +The following statements from Linus Torvalds provide some insight into Linux +"no regressions" rule and how he expects regressions to be handled: - * From `2017-10-26 (1/2) - `_:: +On how quickly regressions should be fixed +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - If you break existing user space setups THAT IS A REGRESSION. +* From `2026-01-22 `_:: - It's not ok to say "but we'll fix the user space setup". + But a user complaining should basically result in an immediate fix - + possibly a "revert and rethink". - Really. NOT OK. + With a later clarification on `2026-01-28 `_:: - [...] + It's also worth noting that "immediate" obviously doesn't mean "right + this *second* when the problem has been reported". - The first rule is: + But if it's a regression with a known commit that caused it, I think + the rule of thumb should generally be "within a week", preferably + before the next rc. - - we don't cause regressions +* From `2023-04-21 `_:: - and the corollary is that when regressions *do* occur, we admit to - them and fix them, instead of blaming user space. + Known-broken commits either + (a) get a timely fix that doesn't have other questions + or + (b) get reverted - The fact that you have apparently been denying the regression now for - three weeks means that I will revert, and I will stop pulling apparmor - requests until the people involved understand how kernel development - is done. +* From `2021-09-20(2) `_:: - * From `2017-10-26 (2/2) - `_:: + [...] review shouldn't hold up reported regressions of existing code. That's + just basic _testing_ - either the fix should be applied, or - if the fix is + too invasive or too ugly - the problematic source of the regression should + be reverted. - People should basically always feel like they can update their kernel - and simply not have to worry about it. + Review should be about new code, it shouldn't be holding up "there's a + bug report, here's the obvious fix". - I refuse to introduce "you can only update the kernel if you also - update that other program" kind of limitations. If the kernel used to - work for you, the rule is that it continues to work for you. +* From `2023-05-08 `_:: - There have been exceptions, but they are few and far between, and they - generally have some major and fundamental reasons for having happened, - that were basically entirely unavoidable, and people _tried_hard_ to - avoid them. Maybe we can't practically support the hardware any more - after it is decades old and nobody uses it with modern kernels any - more. Maybe there's a serious security issue with how we did things, - and people actually depended on that fundamentally broken model. Maybe - there was some fundamental other breakage that just _had_ to have a - flag day for very core and fundamental reasons. + If something doesn't even build, it should damn well be fixed ASAP. - And notice that this is very much about *breaking* peoples environments. +On how fixing regressions with reverts can help prevent maintainer burnout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Behavioral changes happen, and maybe we don't even support some - feature any more. There's a number of fields in /proc//stat that - are printed out as zeroes, simply because they don't even *exist* in - the kernel any more, or because showing them was a mistake (typically - an information leak). But the numbers got replaced by zeroes, so that - the code that used to parse the fields still works. The user might not - see everything they used to see, and so behavior is clearly different, - but things still _work_, even if they might no longer show sensitive - (or no longer relevant) information. +* From `2026-01-28 `_:: - But if something actually breaks, then the change must get fixed or - reverted. And it gets fixed in the *kernel*. Not by saying "well, fix - your user space then". It was a kernel change that exposed the - problem, it needs to be the kernel that corrects for it, because we - have a "upgrade in place" model. We don't have a "upgrade with new - user space". + > So how can I/we make "immediate fixes" happen more often without + > contributing to maintainer burnout? - And I seriously will refuse to take code from people who do not - understand and honor this very simple rule. + [...] the "revert and rethink" model [...] often a good idea in general [...] - This rule is also not going to change. + Exactly so that maintainers don't get stressed out over having a pending + problem report that people keep pestering them about. - And yes, I realize that the kernel is "special" in this respect. I'm - proud of it. + I think people are sometimes a bit too bought into whatever changes + they made, and reverting is seen as "too drastic", but I think it's + often the quick and easy solution for when there isn't some obvious + response to a regression report. - I have seen, and can point to, lots of projects that go "We need to - break that use case in order to make progress" or "you relied on - undocumented behavior, it sucks to be you" or "there's a better way to - do what you want to do, and you have to change to that new better - way", and I simply don't think that's acceptable outside of very early - alpha releases that have experimental users that know what they signed - up for. The kernel hasn't been in that situation for the last two - decades. +On mainlining fixes when the last -rc or a new release is close +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - We do API breakage _inside_ the kernel all the time. We will fix - internal problems by saying "you now need to do XYZ", but then it's - about internal kernel API's, and the people who do that then also - obviously have to fix up all the in-kernel users of that API. Nobody - can say "I now broke the API you used, and now _you_ need to fix it - up". Whoever broke something gets to fix it too. +* From `2026-02-01 `_:: - And we simply do not break user space. + So I think I'd rather see them hit rc8 (later today) and have a week + of testing in my tree and be reverted if they cause problems, than + have them go in after rc8 and then cause problems in the 6.19 release + instead. - * From `2020-05-21 - `_:: +* From `2023-04-20 `_:: - The rules about regressions have never been about any kind of - documented behavior, or where the code lives. + But something like this, where the regression was in the previous release + and it's just a clear fix with no semantic subtlety, I consider to be just a + regular regression that should be expedited - partly to make it into stable, + and partly to avoid having to put the fix into _another_ stable kernel. - The rules about regressions are always about "breaks user workflow". +On sending merge requests with just one fix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Users are literally the _only_ thing that matters. +* From `2024-04-24 `_:: - No amount of "you shouldn't have used this" or "that behavior was - undefined, it's your own fault your app broke" or "that used to work - simply because of a kernel bug" is at all relevant. + If the issue is just that there's nothing else happening, I think people + should just point me to the patch and say "can you apply this single fix?" - Now, reality is never entirely black-and-white. So we've had things - like "serious security issue" etc that just forces us to make changes - that may break user space. But even then the rule is that we don't - really have other options that would allow things to continue. +* From `2023-04-20 `_:: - And obviously, if users take years to even notice that something - broke, or if we have sane ways to work around the breakage that - doesn't make for too much trouble for users (ie "ok, there are a - handful of users, and they can use a kernel command line to work - around it" kind of things) we've also been a bit less strict. + I'm always open to direct fixes when there is no controversy about the fix. + No problem. I still happily deal with individual patches. - But no, "that was documented to be broken" (whether it's because the - code was in staging or because the man-page said something else) is - irrelevant. If staging code is so useful that people end up using it, - that means that it's basically regular kernel code with a flag saying - "please clean this up". +On the importance of pointing to bug reports using Link:/Closes: tags +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The other side of the coin is that people who talk about "API - stability" are entirely wrong. API's don't matter either. You can make - any changes to an API you like - as long as nobody notices. +* From `2025-07-29(1) `_:: - Again, the regression rule is not about documentation, not about - API's, and not about the phase of the moon. + [...] revert like this, it really would be good to link to the problems, so + that when people try to re-enable it, they have the history for why it + didn't work the first time. - It's entirely about "we caused problems for user space that used to work". +* From `2022-05-08 `_:: - * From `2017-11-05 - `_:: + So I have to once more complain [...] - And our regression rule has never been "behavior doesn't change". - That would mean that we could never make any changes at all. + [...] There's no link to the actual problem the patch fixes. - For example, we do things like add new error handling etc all the - time, which we then sometimes even add tests for in our kselftest - directory. +* From `2022-06-22 `_:: - So clearly behavior changes all the time and we don't consider that a - regression per se. + See, *that* link [to the report] would have been useful in the commit. - The rule for a regression for the kernel is that some real user - workflow breaks. Not some test. Not a "look, I used to be able to do - X, now I can't". +On why the "no regressions" rule exists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * From `2018-08-03 - `_:: +* From `2026-01-22 `_:: - YOU ARE MISSING THE #1 KERNEL RULE. + But the basic rule is: be so good about backwards compatibility that + users never have to worry about upgrading. They should absolutely feel + confident that any kernel-reported problem will either be solved, or + have an easy solution that is appropriate for *them* (ie a + non-technical user shouldn't be expected to be able to do a lot). - We do not regress, and we do not regress exactly because your are 100% wrong. + Because the last thing we want is people holding back from trying new + kernels. - And the reason you state for your opinion is in fact exactly *WHY* you - are wrong. +* From `2024-05-28 `_:: - Your "good reasons" are pure and utter garbage. + I introduced that "no regressions" rule something like two decades + ago, because people need to be able to update their kernel without + fear of something they relied on suddenly stopping to work. - The whole point of "we do not regress" is so that people can upgrade - the kernel and never have to worry about it. +* From `2018-08-03 `_:: - > Kernel had a bug which has been fixed + The whole point of "we do not regress" is so that people can upgrade + the kernel and never have to worry about it. - That is *ENTIRELY* immaterial. + [...] - Guys, whether something was buggy or not DOES NOT MATTER. + Because the only thing that matters IS THE USER. - Why? +* From `2017-10-26(1) `_:: - Bugs happen. That's a fact of life. Arguing that "we had to break - something because we were fixing a bug" is completely insane. We fix - tens of bugs every single day, thinking that "fixing a bug" means that - we can break something is simply NOT TRUE. + If the kernel used to work for you, the rule is that it continues to work + for you. - So bugs simply aren't even relevant to the discussion. They happen, - they get found, they get fixed, and it has nothing to do with "we - break users". + [...] - Because the only thing that matters IS THE USER. + People should basically always feel like they can update their kernel + and simply not have to worry about it. - How hard is that to understand? + I refuse to introduce "you can only update the kernel if you also + update that other program" kind of limitations. If the kernel used to + work for you, the rule is that it continues to work for you. - Anybody who uses "but it was buggy" as an argument is entirely missing - the point. As far as the USER was concerned, it wasn't buggy - it - worked for him/her. +On exceptions to the "no regressions" rule +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Maybe it worked *because* the user had taken the bug into account, - maybe it worked because the user didn't notice - again, it doesn't - matter. It worked for the user. +* From `2026-01-22 `_:: - Breaking a user workflow for a "bug" is absolutely the WORST reason - for breakage you can imagine. + There are _very_ few exceptions to that rule, the main one being "the + problem was a fundamental huge and gaping security issue and we *had* to + make that change, and we couldn't even make your limited use-case just + continue to work". - It's basically saying "I took something that worked, and I broke it, - but now it's better". Do you not see how f*cking insane that statement - is? + The other exception is "the problem was reported years after it was + introduced, and now most people rely on the new behavior". - And without users, your program is not a program, it's a pointless - piece of code that you might as well throw away. + [...] - Seriously. This is *why* the #1 rule for kernel development is "we - don't break users". Because "I fixed a bug" is absolutely NOT AN - ARGUMENT if that bug fix broke a user setup. You actually introduced a - MUCH BIGGER bug by "fixing" something that the user clearly didn't - even care about. + Now, if it's one or two users and you can just get them to recompile, + that's one thing. Niche hardware and odd use-cases can sometimes be + solved that way, and regressions can sometimes be fixed by handholding + every single reporter if the reporter is willing and able to change + his or her workflow. - And dammit, we upgrade the kernel ALL THE TIME without upgrading any - other programs at all. It is absolutely required, because flag-days - and dependencies are horribly bad. +* From `2023-04-20 `_:: - And it is also required simply because I as a kernel developer do not - upgrade random other tools that I don't even care about as I develop - the kernel, and I want any of my users to feel safe doing the same - time. + And yes, I do consider "regression in an earlier release" to be a + regression that needs fixing. - So no. Your rule is COMPLETELY wrong. If you cannot upgrade a kernel - without upgrading some other random binary, then we have a problem. + There's obviously a time limit: if that "regression in an earlier + release" was a year or more ago, and just took forever for people to + notice, and it had semantic changes that now mean that fixing the + regression could cause a _new_ regression, then that can cause me to + go "Oh, now the new semantics are what we have to live with". - * From `2021-06-05 - `_:: +* From `2017-10-26(2) `_:: - THERE ARE NO VALID ARGUMENTS FOR REGRESSIONS. + There have been exceptions, but they are few and far between, and they + generally have some major and fundamental reasons for having happened, + that were basically entirely unavoidable, and people _tried_hard_ to + avoid them. Maybe we can't practically support the hardware any more + after it is decades old and nobody uses it with modern kernels any + more. Maybe there's a serious security issue with how we did things, + and people actually depended on that fundamentally broken model. Maybe + there was some fundamental other breakage that just _had_ to have a + flag day for very core and fundamental reasons. - Honestly, security people need to understand that "not working" is not - a success case of security. It's a failure case. +On situations where updating something in userspace can resolve regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Yes, "not working" may be secure. But security in that case is *pointless*. +* From `2018-08-03 `_:: - * From `2011-05-06 (1/3) - `_:: + And dammit, we upgrade the kernel ALL THE TIME without upgrading any + other programs at all. It is absolutely required, because flag-days + and dependencies are horribly bad. - Binary compatibility is more important. + And it is also required simply because I as a kernel developer do not + upgrade random other tools that I don't even care about as I develop the + kernel, and I want any of my users to feel safe doing the same time. - And if binaries don't use the interface to parse the format (or just - parse it wrongly - see the fairly recent example of adding uuid's to - /proc/self/mountinfo), then it's a regression. +* From `2017-10-26(3) `_:: - And regressions get reverted, unless there are security issues or - similar that makes us go "Oh Gods, we really have to break things". + But if something actually breaks, then the change must get fixed or + reverted. And it gets fixed in the *kernel*. Not by saying "well, fix your + user space then". It was a kernel change that exposed the problem, it needs + to be the kernel that corrects for it, because we have a "upgrade in place" + model. We don't have a "upgrade with new user space". - I don't understand why this simple logic is so hard for some kernel - developers to understand. Reality matters. Your personal wishes matter - NOT AT ALL. + And I seriously will refuse to take code from people who do not understand + and honor this very simple rule. - If you made an interface that can be used without parsing the - interface description, then we're stuck with the interface. Theory - simply doesn't matter. + This rule is also not going to change. - You could help fix the tools, and try to avoid the compatibility - issues that way. There aren't that many of them. + And yes, I realize that the kernel is "special" in this respect. I'm proud + of it. - From `2011-05-06 (2/3) - `_:: +* From `2017-10-26(4) `_:: - it's clearly NOT an internal tracepoint. By definition. It's being - used by powertop. + If you break existing user space setups THAT IS A REGRESSION. - From `2011-05-06 (3/3) - `_:: + It's not ok to say "but we'll fix the user space setup". - We have programs that use that ABI and thus it's a regression if they break. + Really. NOT OK. - * From `2012-07-06 `_:: +On what qualifies as userspace interface, ABI, API, documented interfaces, etc. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - > Now this got me wondering if Debian _unstable_ actually qualifies as a - > standard distro userspace. +* From `2026-01-20 `_:: - Oh, if the kernel breaks some standard user space, that counts. Tons - of people run Debian unstable + So I absolutely detest the whole notion of "ABI changes". It's a + meaningless concept, and I hate it with a passion, [...] - * From `2019-09-15 - `_:: + The Linux rule for regressions is basically based on the philosophical + question of "If a tree falls in the forest, and nobody is around to + hear it, does it make a sound?". - One _particularly_ last-minute revert is the top-most commit (ignoring - the version change itself) done just before the release, and while - it's very annoying, it's perhaps also instructive. + So the only thing that matters is if something breaks user-*conscious* + behavior. - What's instructive about it is that I reverted a commit that wasn't - actually buggy. In fact, it was doing exactly what it set out to do, - and did it very well. In fact it did it _so_ well that the much - improved IO patterns it caused then ended up revealing a user-visible - regression due to a real bug in a completely unrelated area. + And when that happens, the distinction between "bug fix" and "new + feature" and "ABI change" matters not one whit, and the change needs + to be done differently. - The actual details of that regression are not the reason I point that - revert out as instructive, though. It's more that it's an instructive - example of what counts as a regression, and what the whole "no - regressions" kernel rule means. The reverted commit didn't change any - API's, and it didn't introduce any new bugs. But it ended up exposing - another problem, and as such caused a kernel upgrade to fail for a - user. So it got reverted. + [...] - The point here being that we revert based on user-reported _behavior_, - not based on some "it changes the ABI" or "it caused a bug" concept. - The problem was really pre-existing, and it just didn't happen to - trigger before. The better IO patterns introduced by the change just - happened to expose an old bug, and people had grown to depend on the - previously benign behavior of that old issue. + I just wanted to point out that the argument about whether it's an ABI + change or not is irrelevant. If it turns out that some program - not a test + script, but something with relevance to conscious user expectations ~ + depended on the old broken behavior, then it needs to be done some other + way. - And never fear, we'll re-introduce the fix that improved on the IO - patterns once we've decided just how to handle the fact that we had a - bad interaction with an interface that people had then just happened - to rely on incidental behavior for before. It's just that we'll have - to hash through how to do that (there are no less than three different - patches by three different developers being discussed, and there might - be more coming...). In the meantime, I reverted the thing that exposed - the problem to users for this release, even if I hope it will be - re-introduced (perhaps even backported as a stable patch) once we have - consensus about the issue it exposed. +* From `2026-02-13 `_:: - Take-away from the whole thing: it's not about whether you change the - kernel-userspace ABI, or fix a bug, or about whether the old code - "should never have worked in the first place". It's about whether - something breaks existing users' workflow. + > [...] this should not fall under the don't break user space rule [...] - Anyway, that was my little aside on the whole regression thing. Since - it's that "first rule of kernel programming", I felt it is perhaps - worth just bringing it up every once in a while + Note that the rule is about breaking *users*, not breaking user space per + se. [...] + + If some user setup breaks, things need fixing. + + [...] but I want to make it very clear that there are no excuses about "user + space applications". + +* From `2021-09-20(4) `_:: + + [...] a regression is a bit like Schrödinger's cat - if nobody is around + to notice it and it doesn't actually affect any real workload, then you + can treat the regression as if it doesn't exist. + +* From `2020-05-21 `_:: + + The rules about regressions have never been about any kind of documented + behavior, or where the code lives. + + The rules about regressions are always about "breaks user workflow". + + Users are literally the _only_ thing that matters. + +* From `2019-09-15 `_:: + + One _particularly_ last-minute revert is the top-most commit (ignoring + the version change itself) done just before the release, and while + it's very annoying, it's perhaps also instructive. + + What's instructive about it is that I reverted a commit that wasn't + actually buggy. In fact, it was doing exactly what it set out to do, + and did it very well. In fact it did it _so_ well that the much + improved IO patterns it caused then ended up revealing a user-visible + regression due to a real bug in a completely unrelated area. + + The actual details of that regression are not the reason I point that + revert out as instructive, though. It's more that it's an instructive + example of what counts as a regression, and what the whole "no + regressions" kernel rule means. + + [...] The reverted commit didn't change any API's, and it didn't introduce + any new bugs. But it ended up exposing another problem, and as such caused + a kernel upgrade to fail for a user. So it got reverted. + + The point here being that we revert based on user-reported _behavior_, not + based on some "it changes the ABI" or "it caused a bug" concept. The problem + was really pre-existing, and it just didn't happen to trigger before. [...] + + Take-away from the whole thing: it's not about whether you change the + kernel-userspace ABI, or fix a bug, or about whether the old code + "should never have worked in the first place". It's about whether + something breaks existing users' workflow. + +* From `2017-11-05 `_:: + + And our regression rule has never been "behavior doesn't change". + That would mean that we could never make any changes at all. + +* From `2020-05-21 `_:: + + No amount of "you shouldn't have used this" or "that behavior was + undefined, it's your own fault your app broke" or "that used to work + simply because of a kernel bug" is at all relevant. + +* From `2021-05-21 `_:: + + But no, "that was documented to be broken" (whether it's because the code + was in staging or because the man-page said something else) is irrelevant. + If staging code is so useful that people end up using it, that means that + it's basically regular kernel code with a flag saying "please clean this + up". + + [...] + + The other side of the coin is that people who talk about "API stability" are + entirely wrong. API's don't matter either. You can make any changes to an + API you like - as long as nobody notices. + + Again, the regression rule is not about documentation, not about API's, and + not about the phase of the moon. + +* From `2012-07-06 `_:: + + > Now this got me wondering if Debian _unstable_ actually qualifies as a + > standard distro userspace. + + Oh, if the kernel breaks some standard user space, that counts. Tons + of people run Debian unstable + +* From `2011-05-06 `_:: + + It's clearly NOT an internal tracepoint. By definition. It's being + used by powertop. + +On regressions noticed by users or test-suites/CIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2026-01-22 `_:: + + Users complaining is the only real line in the end. + + [...] a test-suite complaining is then often a *very* good indication that + maybe users will hit some problem, and test suite issues should be taken + very seriously [...] + + But a test-suite error isn't necessarily where you have to draw the + line - it's a big red flag [...] + +* From `2024-29-01 `_:: + + The "no regressions" rule is not about made-up "if I do this, behavior + changes". + + The "no regressions" rule is about *users*. + + If you have an actual user that has been doing insane things, and we + change something, and now the insane thing no longer works, at that + point it's a regression, and we'll sigh, and go "Users are insane" and + have to fix it. + + But if you have some random test that now behaves differently, it's + not a regression. It's a *warning* sign, sure: tests are useful. + +On accepting when a regression occurred +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2026-01-22 `_:: + + But starting to argue about users reporting breaking changes is + basically the final line for me. I have a couple of people that I have + in my spam block-list and refuse to have anything to do with, and they + have generally been about exactly that. + + Note how it's not about making mistakes and _causing_ the regression. + That's normal. That's development. But then arguing about it is a + no-no. + +* From `2024-06-23 `_:: + + We don't introduce regressions and then blame others. + + There's a very clear rule in kernel development: things that break + other things ARE NOT FIXES. + + EVER. + + They get reverted, or the thing they broke gets fixed. + +* From `2021-06-05 `_:: + + THERE ARE NO VALID ARGUMENTS FOR REGRESSIONS. + + Honestly, security people need to understand that "not working" is not + a success case of security. It's a failure case. + + Yes, "not working" may be secure. But security in that case is *pointless*. + +* From `2017-10-26(5) `_:: + + [...] when regressions *do* occur, we admit to them and fix them, instead of + blaming user space. + + The fact that you have apparently been denying the regression now for + three weeks means that I will revert, and I will stop pulling apparmor + requests until the people involved understand how kernel development + is done. + +On back-and-forth +~~~~~~~~~~~~~~~~~ + +* From `2024-05-28 `_:: + + The "no regressions" rule is that we do not introduce NEW bugs. + + It *literally* came about because we had an endless dance of "fix two + bugs, introduce one new one", and that then resulted in a system that + you cannot TRUST. + +* From `2021-09-20(1) `_:: + + And the thing that makes regressions special is that back when I + wasn't so strict about these things, we'd end up in endless "seesaw + situations" where somebody would fix something, it would break + something else, then that something else would break, and it would + never actually converge on anything reliable at all. + +* From `2015-08-13 `_:: + + The strict policy of no regressions actually originally started mainly wrt + suspend/resume issues, where the "fix one machine, break another" kind of + back-and-forth caused endless problems, and meant that we didn't actually + necessarily make any forward progress, just moving a problem around. + +On changes with a risk of causing regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2023-06-02 `_:: + + So what I think you should do is to fix the bug right, with a clean + patch, and no crazy hacks. That is something we can then apply and + test. All the while knowing full well that "uhhuh, this is a visible + change, we may have to revert it". + + If then some *real* load ends up showing a regression, we may just be + screwed. Our current behavior may be buggy, but we have the rule that + once user space depends on kernel bugs, they become features pretty + much by definition, however much we might dislike it. + +On in-kernel workarounds to avoid regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2017-10-26(6) `_:: + + Behavioral changes happen, and maybe we don't even support some + feature any more. There's a number of fields in /proc//stat that + are printed out as zeroes, simply because they don't even *exist* in + the kernel any more, or because showing them was a mistake (typically + an information leak). But the numbers got replaced by zeroes, so that + the code that used to parse the fields still works. The user might not + see everything they used to see, and so behavior is clearly different, + but things still _work_, even if they might no longer show sensitive + (or no longer relevant) information. + +On regressions caused by bugfixes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2018-08-03 `_:: + + > Kernel had a bug which has been fixed + + That is *ENTIRELY* immaterial. + + Guys, whether something was buggy or not DOES NOT MATTER. + + [...] + + It's basically saying "I took something that worked, and I broke it, + but now it's better". Do you not see how f*cking insane that statement + is? + +On internal API changes +~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2017-10-26(7) `_:: + + We do API breakage _inside_ the kernel all the time. We will fix + internal problems by saying "you now need to do XYZ", but then it's + about internal kernel API's, and the people who do that then also + obviously have to fix up all the in-kernel users of that API. Nobody + can say "I now broke the API you used, and now _you_ need to fix it + up". Whoever broke something gets to fix it too. + +On regressions only found after a long time +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2024-03-28 `_:: + + I'm definitely not reverting a patch from almost a decade ago as a + regression. + + If it took that long to find, it can't be that critical of a regression. + + So yes, let's treat it as a regular bug. + +On testing regressions fixes in linux-next +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* On `maintainers summit 2024 `_:: + + So running fixes though linux-next is just a waste of time. + +On a few other aspects related to regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* From `2025-07-29(2) `_ + [which `is not quite a regression, but a huge inconvenience `_]:: + + I no longer have sound. + + I also suspect that it's purely because "make oldconfig" doesn't work, + and probably turned off my old Intel HDA settings. Or something. + + Renaming config parameters is *bad*. I've harped on the Kconfig phase + of the kernel build probably being our nastiest point, and a real pain + point to people getting involved with development simply because + building your own kernel can be so daunting with hundreds of fairly + esoteric questions. .. end-of-content From 1722b500d22ce3fa327d510c255725eb213a9011 Mon Sep 17 00:00:00 2001 From: Ryan Cheevers Date: Mon, 9 Mar 2026 01:00:15 -0500 Subject: [PATCH 038/162] docs: fix typo in housekeeping Signed-off-by: Ryan Cheevers Signed-off-by: Jonathan Corbet Message-ID: <20260309060015.2349939-1-cheeversr0@gmail.com> --- Documentation/core-api/housekeeping.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/core-api/housekeeping.rst b/Documentation/core-api/housekeeping.rst index e5417302774c..92c6e53cea75 100644 --- a/Documentation/core-api/housekeeping.rst +++ b/Documentation/core-api/housekeeping.rst @@ -15,7 +15,7 @@ various deferrals etc... Sometimes housekeeping is just some unbound work (unbound workqueues, unbound timers, ...) that gets easily assigned to non-isolated CPUs. But sometimes housekeeping is tied to a specific CPU and requires -elaborated tricks to be offloaded to non-isolated CPUs (RCU_NOCB, remote +elaborate tricks to be offloaded to non-isolated CPUs (RCU_NOCB, remote scheduler tick, etc...). Thus, a housekeeping CPU can be considered as the reverse of an isolated From fcbf51dd164e52cac4df10bd0c7a08b6e08dd0f4 Mon Sep 17 00:00:00 2001 From: Haoyang LIU Date: Sun, 8 Mar 2026 19:13:13 +0800 Subject: [PATCH 039/162] tools/docs/checktransupdate.py: add support for scanning directory Origin script can only accept a file as parameter, this commit enables it to scan a directory. Usage example: ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools And it will output something like: """ [1772967203.351603] Documentation/translations/zh_CN/dev-tools/kmemleak.rst [1772967205.074201] commit 7591c127f3b1 ("kmemleak: iommu/iova: fix transient kmemleak false positive") [1772967205.074337] 1 commits needs resolving in total [1772967205.301705] Documentation/translations/zh_CN/dev-tools/index.rst [1772967206.912395] commit a592a36e4937 ("Documentation: use a source-read extension for the index link boilerplate") [1772967206.921424] commit 6eac13c87680 ("Documentation: dev-tools: add container.rst page") [1772967206.930220] commit 8f32441d7a53 ("Documentation: Add documentation for Compiler-Based Context Analysis") [1772967206.939002] commit 1e9ddbb2cd34 ("docs: Pull LKMM documentation into dev-tools book") [1772967206.948636] commit d5af79c05e93 ("Documentation: move dev-tools debugging files to process/debugging/") [1772967206.957562] commit d5dc95836147 ("kbuild: Add Propeller configuration for kernel build") [1772967206.966255] commit 315ad8780a12 ("kbuild: Add AutoFDO support for Clang build") [1772967206.966410] 7 commits needs resolving in total """ Signed-off-by: Haoyang LIU [jc: tweaked coding style] Signed-off-by: Jonathan Corbet Message-ID: <20260308111314.27333-1-tttturtleruss@gmail.com> --- tools/docs/checktransupdate.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/docs/checktransupdate.py b/tools/docs/checktransupdate.py index e894652369a5..f296a969f02c 100755 --- a/tools/docs/checktransupdate.py +++ b/tools/docs/checktransupdate.py @@ -13,6 +13,8 @@ The usage is as follows: This will print all the files that need to be updated or translated in the zh_CN locale. - tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst This will only print the status of the specified file. +- tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools +This will print the status of all files under the directory. The output is something like: Documentation/dev-tools/kfence.rst @@ -262,7 +264,7 @@ def main(): help='Set the logging file (default: checktransupdate.log)') parser.add_argument( - "files", nargs="*", help="Files to check, if not specified, check all files" + "files", nargs="*", help="Files or directories to check, if not specified, check all files" ) args = parser.parse_args() @@ -293,6 +295,16 @@ def main(): if args.print_missing_translations: logging.info(os.path.relpath(os.path.abspath(file), linux_path)) logging.info("No translation in the locale of %s\n", args.locale) + else: + # check if the files are directories or files + new_files = [] + for file in files: + if os.path.isfile(file): + new_files.append(file) + elif os.path.isdir(file): + # for directories, list all files in the directory and its subfolders + new_files.extend(list_files_with_excluding_folders(file, [], "rst")) + files = new_files files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files)) From 4fe1e1dcca07a8dfd9534bbb9bd40e5ea9f594cb Mon Sep 17 00:00:00 2001 From: LIU Haoyang Date: Sun, 8 Mar 2026 18:08:50 +0800 Subject: [PATCH 040/162] docs/dev-tools: fix a broken URL in dev-tools/coccinelle.rst The original supplemental documentation for coccicheck is https://bottest.wiki.kernel.org/coccicheck, which redirects to a not found page, thus change it to https://bottest.wiki.kernel.org/coccicheck.html, which adds a suffix to original URL to make it direct to the right page. Signed-off-by: LIU Haoyang Reviewed-by: Dongliang Mu Signed-off-by: Jonathan Corbet Message-ID: <20260308100851.341-1-tttturtleruss@gmail.com> --- Documentation/dev-tools/coccinelle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst index 2b942e3c8049..f73ccf5397f3 100644 --- a/Documentation/dev-tools/coccinelle.rst +++ b/Documentation/dev-tools/coccinelle.rst @@ -61,7 +61,7 @@ Supplemental documentation For supplemental documentation refer to the wiki: -https://bottest.wiki.kernel.org/coccicheck +https://bottest.wiki.kernel.org/coccicheck.html The wiki documentation always refers to the linux-next version of the script. From 73f29b02e78e2d45c97024d8c05a798b4b235383 Mon Sep 17 00:00:00 2001 From: Ariful Islam Shoikot Date: Sat, 7 Mar 2026 17:40:06 +0600 Subject: [PATCH 041/162] Documentation/mm: Fix typo in NUMA paragraph Fixed a typo in Documentation/mm/numa.rst: -changed 'allocated' to 'allocate' in the paragraph about memoryless nodes. Signed-off-by: Ariful Islam Shoikot Signed-off-by: Jonathan Corbet Message-ID: <20260307114006.33183-1-islamarifulshoikat@gmail.com> --- Documentation/mm/numa.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/mm/numa.rst b/Documentation/mm/numa.rst index 0f1b56809dca..b765295c6e85 100644 --- a/Documentation/mm/numa.rst +++ b/Documentation/mm/numa.rst @@ -140,7 +140,7 @@ this. If the architecture supports--does not hide--memoryless nodes, then CPUs attached to memoryless nodes would always incur the fallback path overhead -or some subsystems would fail to initialize if they attempted to allocated +or some subsystems would fail to initialize if they attempted to allocate memory exclusively from a node without memory. To support such architectures transparently, kernel subsystems can use the numa_mem_id() or cpu_to_mem() function to locate the "local memory node" for the calling or From 17eb360d7df58708f0c16b48e6b29bc614d6ffc7 Mon Sep 17 00:00:00 2001 From: "David Hildenbrand (Arm)" Date: Fri, 6 Mar 2026 09:19:16 +0100 Subject: [PATCH 042/162] docs: filesystems: clarify KernelPageSize vs. MMUPageSize in smaps There was recently some confusion around THPs and the interaction with KernelPageSize / MMUPageSize. Historically, these entries always correspond to the smallest size we could encounter, not any current usage of transparent huge pages or larger sizes used by the MMU. Ever since we added THP support many, many years ago, these entries would keep reporting the smallest (fallback) granularity in a VMA. For this reason, they default to PAGE_SIZE for all VMAs except for VMAs where we have the guarantee that the system and the MMU will always use larger page sizes. hugetlb, for example, exposes a custom vm_ops->pagesize callback to handle that. Similarly, dax/device exposes a custom vm_ops->pagesize callback and provides similar guarantees. Let's clarify the historical meaning of KernelPageSize / MMUPageSize, and point at "AnonHugePages", "ShmemPmdMapped" and "FilePmdMapped" regarding PMD entries. While at it, document "FilePmdMapped", clarify what the "AnonHugePages" and "ShmemPmdMapped" entries really mean, and make it clear that there are no other entries for other THP/folio sizes or mappings. Also drop the duplicate "KernelPageSize" and "MMUPageSize" entries in the example. Link: https://lore.kernel.org/all/20260225232708.87833-1-ak@linux.intel.com/ Reviewed-by: Zi Yan Reviewed-by: Lance Yang Acked-by: Vlastimil Babka (SUSE) Cc: Andrew Morton Cc: Lorenzo Stoakes Cc: Zi Yan Cc: Baolin Wang Cc: Liam R. Howlett Cc: Nico Pache Cc: Ryan Roberts Cc: Dev Jain Cc: Barry Song Cc: Lance Yang Cc: Jonathan Corbet Cc: Shuah Khan Cc: Usama Arif Cc: Andi Kleen Signed-off-by: David Hildenbrand (Arm) Reviewed-by: Lorenzo Stoakes (Oracle) Signed-off-by: Jonathan Corbet Message-ID: <20260306081916.38872-1-david@kernel.org> --- Documentation/filesystems/proc.rst | 40 +++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index b0c0d1b45b99..e2d22a424dcd 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -464,26 +464,37 @@ Memory Area, or VMA) there is a series of lines such as the following:: KSM: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB + FilePmdMapped: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB - KernelPageSize: 4 kB - MMUPageSize: 4 kB Locked: 0 kB THPeligible: 0 VmFlags: rd ex mr mw me dw The first of these lines shows the same information as is displayed for the mapping in /proc/PID/maps. Following lines show the size of the -mapping (size); the size of each page allocated when backing a VMA -(KernelPageSize), which is usually the same as the size in the page table -entries; the page size used by the MMU when backing a VMA (in most cases, -the same as KernelPageSize); the amount of the mapping that is currently -resident in RAM (RSS); the process's proportional share of this mapping -(PSS); and the number of clean and dirty shared and private pages in the -mapping. +mapping (size); the smallest possible page size allocated when backing a +VMA (KernelPageSize), which is the granularity in which VMA modifications +can be performed; the smallest possible page size that could be used by the +MMU (MMUPageSize) when backing a VMA; the amount of the mapping that is +currently resident in RAM (RSS); the process's proportional share of this +mapping (PSS); and the number of clean and dirty shared and private pages +in the mapping. + +"KernelPageSize" always corresponds to "MMUPageSize", except when a larger +kernel page size is emulated on a system with a smaller page size used by the +MMU, which is the case for some PPC64 setups with hugetlb. Furthermore, +"KernelPageSize" and "MMUPageSize" always correspond to the smallest +possible granularity (fallback) that can be encountered in a VMA throughout +its lifetime. These values are not affected by Transparent Huge Pages +being in effect, or any usage of larger MMU page sizes (either through +architectural huge-page mappings or other explicit/implicit coalescing of +virtual ranges performed by the MMU). "AnonHugePages", "ShmemPmdMapped" and +"FilePmdMapped" provide insight into the usage of PMD-level architectural +huge-page mappings. The "proportional set size" (PSS) of a process is the count of pages it has in memory, where each page is divided by the number of processes sharing it. @@ -528,10 +539,15 @@ pressure if the memory is clean. Please note that the printed value might be lower than the real value due to optimizations used in the current implementation. If this is not desirable please file a bug report. -"AnonHugePages" shows the amount of memory backed by transparent hugepage. +"AnonHugePages", "ShmemPmdMapped" and "FilePmdMapped" show the amount of +memory backed by Transparent Huge Pages that are currently mapped by +architectural huge-page mappings at the PMD level. "AnonHugePages" +corresponds to memory that does not belong to a file, "ShmemPmdMapped" to +shared memory (shmem/tmpfs) and "FilePmdMapped" to file-backed memory +(excluding shmem/tmpfs). -"ShmemPmdMapped" shows the amount of shared (shmem/tmpfs) memory backed by -huge pages. +There are no dedicated entries for Transparent Huge Pages (or similar concepts) +that are not mapped by architectural huge-page mappings at the PMD level. "Shared_Hugetlb" and "Private_Hugetlb" show the amounts of memory backed by hugetlbfs page which is *not* counted in "RSS" or "PSS" field for historical From b8e7e03370b924f2c91895296dfb79c8692d21d4 Mon Sep 17 00:00:00 2001 From: Tommaso Cucinotta Date: Wed, 4 Mar 2026 11:28:16 +0100 Subject: [PATCH 043/162] sched/deadline: document new sched_getattr() feature for retrieving current parameters for DEADLINE tasks Document in Documentation/sched/sched-deadline.rst the new capability of sched_getattr() to retrieve, for DEADLINE tasks, the runtime left and absolute deadline (setting the flags syscall parameter to 1), in addition to the static parameters (obtained with flags=0). Signed-off-by: Tommaso Cucinotta Acked-by: Juri Lelli Signed-off-by: Jonathan Corbet Message-ID: <20260304102843.1373905-2-tommaso.cucinotta@santannapisa.it> --- Documentation/scheduler/sched-deadline.rst | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Documentation/scheduler/sched-deadline.rst b/Documentation/scheduler/sched-deadline.rst index d23e4afe1a9a..3ad93cd7b59a 100644 --- a/Documentation/scheduler/sched-deadline.rst +++ b/Documentation/scheduler/sched-deadline.rst @@ -628,10 +628,21 @@ Deadline Task Scheduling * the new scheduling related syscalls that manipulate it, i.e., sched_setattr() and sched_getattr() are implemented. - For debugging purposes, the leftover runtime and absolute deadline of a - SCHED_DEADLINE task can be retrieved through /proc//sched (entries - dl.runtime and dl.deadline, both values in ns). A programmatic way to - retrieve these values from production code is under discussion. + The leftover runtime and absolute deadline of a SCHED_DEADLINE task can be + read using the sched_getattr() syscall, setting the last syscall parameter + flags to the SCHED_GETATTR_FLAG_DL_DYNAMIC=1 value. This updates the + runtime left, converts the absolute deadline in CLOCK_MONOTONIC reference, + then returns these parameters to user-space. The absolute deadline is + returned as the number of nanoseconds since the CLOCK_MONOTONIC time + reference (boot instant), as a u64 in the sched_deadline field of sched_attr, + which can represent nearly 585 years since boot time (calling sched_getattr() + with flags=0 causes retrieval of the static parameters instead). + + For debugging purposes, these parameters can also be retrieved through + /proc//sched (entries dl.runtime and dl.deadline, both values in ns), + but: this is highly inefficient; the returned runtime left is not updated as + done by sched_getattr(); the deadline is provided in kernel rq_clock time + reference, that is not directly usable from user-space. 4.3 Default behavior From 861dcdb6ad6f339a5958764352e626e2af7df4c1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:25:14 +0100 Subject: [PATCH 044/162] docs: kdoc_files: allows the caller to use a different xforms class While the main goal for kernel-doc is to be used inside the Linux Kernel, other open source projects could benefit for it. That's currently the case of QEMU, which has a fork, mainly due to two reasons: - they need an extra C function transform rule; - they handle the html output a little bit different. Add an extra optional argument to make easier for the code to be shared, as, with that, QEMU can just create a new derivated class that will contain its specific rulesets, and just copy the remaining kernel-doc files as-is. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <6b274ddbdcd9d438c6848e00e410a2f65ef80ec2.1772810574.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_files.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 33618c6abec2..c35e033cf123 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -118,7 +118,7 @@ class KernelFiles(): if fname in self.files: return - doc = KernelDoc(self.config, fname, CTransforms()) + doc = KernelDoc(self.config, fname, self.xforms) export_table, entries = doc.parse_kdoc() self.export_table[fname] = export_table @@ -154,7 +154,7 @@ class KernelFiles(): self.error(f"Cannot find file {fname}") - def __init__(self, verbose=False, out_style=None, + def __init__(self, verbose=False, out_style=None, xforms=None, werror=False, wreturn=False, wshort_desc=False, wcontents_before_sections=False, logger=None): @@ -193,6 +193,11 @@ class KernelFiles(): self.config.wshort_desc = wshort_desc self.config.wcontents_before_sections = wcontents_before_sections + if xforms: + self.xforms = xforms + else: + self.xforms = CTransforms() + if not logger: self.config.log = logging.getLogger("kernel-doc") else: From 0d3ab0e4bbfd688bfaef66b6365a71c70a0f0450 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:25:15 +0100 Subject: [PATCH 045/162] docs: kdoc_files: document KernelFiles() ABI The KernelFiles is the main entry point to run kernel-doc, being used by both tools/docs/kernel-doc and Documentation/sphinx/kerneldoc.py. It is also used on QEMU, which also uses the kernel-doc libraries from tools/lib/python/kdoc. Properly describe its ABI contract. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <13eb44c341232564eaf2a9c9de4782369fef57e1.1772810574.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_files.py | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index c35e033cf123..8c2059623949 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -91,7 +91,49 @@ class KernelFiles(): """ Parse kernel-doc tags on multiple kernel source files. - There are two type of parsers defined here: + This is the main entry point to run kernel-doc. This class is initialized + using a series of optional arguments: + + ``verbose`` + If True, enables kernel-doc verbosity. Default: False. + + ``out_style`` + Class to be used to format output. If None (default), + only report errors. + + ``xforms`` + Transforms to be applied to C prototypes and data structs. + If not specified, defaults to xforms = CFunction() + + ``werror`` + If True, treat warnings as errors, retuning an error code on warnings. + + Default: False. + + ``wreturn`` + If True, warns about the lack of a return markup on functions. + + Default: False. + ``wshort_desc`` + If True, warns if initial short description is missing. + + Default: False. + + ``wcontents_before_sections`` + If True, warn if there are contents before sections (deprecated). + This option is kept just for backward-compatibility, but it does + nothing, neither here nor at the original Perl script. + + Default: False. + + ``logger`` + Optional logger class instance. + + If not specified, defaults to use: ``logging.getLogger("kernel-doc")`` + + Note: + There are two type of parsers defined here: + - self.parse_file(): parses both kernel-doc markups and ``EXPORT_SYMBOL*`` macros; - self.process_export_file(): parses only ``EXPORT_SYMBOL*`` macros. From 5828d3564729e61306456fae02e9d0dc9f2e772d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:39 +0100 Subject: [PATCH 046/162] docs: sphinx-build-wrapper: better handle troff .TH markups Using a regular expression to match .TH is problematic, as it doesn't handle well quotation marks. Use shlex instead. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <9436806316d33aaf68625c00ce068463d3917660.1772810752.git.mchehab+huawei@kernel.org> --- tools/docs/sphinx-build-wrapper | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper index b7c149dff06b..e6418e22e2ff 100755 --- a/tools/docs/sphinx-build-wrapper +++ b/tools/docs/sphinx-build-wrapper @@ -576,7 +576,6 @@ class SphinxBuilder: """ re_kernel_doc = re.compile(r"^\.\.\s+kernel-doc::\s*(\S+)") - re_man = re.compile(r'^\.TH "[^"]*" (\d+) "([^"]*)"') if docs_dir == src_dir: # @@ -616,8 +615,7 @@ class SphinxBuilder: fp = None try: for line in result.stdout.split("\n"): - match = re_man.match(line) - if not match: + if not line.startswith(".TH"): if fp: fp.write(line + '\n') continue @@ -625,7 +623,9 @@ class SphinxBuilder: if fp: fp.close() - fname = f"{output_dir}/{match.group(2)}.{match.group(1)}" + # Use shlex here, as it handles well parameters with commas + args = shlex.split(line) + fname = f"{output_dir}/{args[3]}.{args[2]}" if self.verbose: print(f"Creating {fname}") From 0e4c8adad4cacf699672d28e19143dc0b9d145fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:40 +0100 Subject: [PATCH 047/162] docs: sphinx-build-wrapper: don't allow "/" on file names When handling "DOC:" sections, slash characters may be there. Prevent using it at the file names, as this is used for directory separator. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/docs/sphinx-build-wrapper | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper index e6418e22e2ff..d3f0dba13da1 100755 --- a/tools/docs/sphinx-build-wrapper +++ b/tools/docs/sphinx-build-wrapper @@ -625,7 +625,9 @@ class SphinxBuilder: # Use shlex here, as it handles well parameters with commas args = shlex.split(line) - fname = f"{output_dir}/{args[3]}.{args[2]}" + fname = f"{args[3]}.{args[2]}" + fname = fname.replace("/", " ") + fname = f"{output_dir}/{fname}" if self.verbose: print(f"Creating {fname}") From c1873e77434db2c592cfd21dd7d2e34a5c18304f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:41 +0100 Subject: [PATCH 048/162] docs: kdoc_output: use a method to emit the .TH header All man emit functions need to add a .TH header. Move the code to a common function, as we'll be addressing some issues at the common code. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <2e55fcfe8724fde08a78635a1a3f8b449a6adf82.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 34 +++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 4210b91dde5f..fb6b90c54c8a 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -607,7 +607,20 @@ class ManFormat(OutputFormat): "%m %d %Y", ] - def __init__(self, modulename): + def emit_th(self, name, modulename = None, manual=None): + """Emit a title header line.""" + name = name.strip() + + if not manual: + manual = self.manual + + if not modulename: + modulename = self.modulename + + self.data += f'.TH "{modulename}" {self.section} "{name}" ' + self.data += f'"{self.date}" "{manual}" LINUX\n' + + def __init__(self, modulename, section="9", manual="API Manual"): """ Creates class variables. @@ -616,7 +629,11 @@ class ManFormat(OutputFormat): """ super().__init__() + self.modulename = modulename + self.section = section + self.manual = manual + self.symbols = [] dt = None @@ -632,7 +649,7 @@ class ManFormat(OutputFormat): if not dt: dt = datetime.now() - self.man_date = dt.strftime("%B %Y") + self.date = dt.strftime("%B %Y") def arg_name(self, args, name): """ @@ -724,7 +741,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" + self.emit_th(out_name) for section, text in args.sections.items(): self.data += f'.SH "{section}"' + "\n" @@ -734,7 +751,8 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.data += f'.TH "{name}" 9 "{out_name}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n" + self.emit_th(out_name, modulename = name, + manual="Kernel Hacker\'s Manual") self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" @@ -780,7 +798,7 @@ class ManFormat(OutputFormat): def out_enum(self, fname, name, args): out_name = self.arg_name(args, name) - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" + self.emit_th(out_name) self.data += ".SH NAME\n" self.data += f"enum {name} \\- {args['purpose']}\n" @@ -813,7 +831,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) full_proto = args.other_stuff["full_proto"] - self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" + self.emit_th(out_name) self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" @@ -834,7 +852,7 @@ class ManFormat(OutputFormat): purpose = args.get('purpose') out_name = self.arg_name(args, name) - self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" + self.emit_th(out_name) self.data += ".SH NAME\n" self.data += f"typedef {name} \\- {purpose}\n" @@ -849,7 +867,7 @@ class ManFormat(OutputFormat): definition = args.get('definition') out_name = self.arg_name(args, name) - self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" + self.emit_th(out_name) self.data += ".SH NAME\n" self.data += f"{args.type} {name} \\- {purpose}\n" From 43874045faa72b876da361fed4b3c9aeee09ebdb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:42 +0100 Subject: [PATCH 049/162] docs: kdoc_output: remove extra attribute on man .TH headers According with modern documents, groff .TH supports up to 5 arguments, but the logic passes 6. Drop the lastest one ("LINUX"). Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_output.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index fb6b90c54c8a..d0b237c09391 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -618,7 +618,7 @@ class ManFormat(OutputFormat): modulename = self.modulename self.data += f'.TH "{modulename}" {self.section} "{name}" ' - self.data += f'"{self.date}" "{manual}" LINUX\n' + self.data += f'"{self.date}" "{manual}"\n' def __init__(self, modulename, section="9", manual="API Manual"): """ From 31938f120fa261b983fed3315239fe1c5fc4e6e7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:43 +0100 Subject: [PATCH 050/162] docs: kdoc_output: use a single manual for everything There's no reason why functions will be on a different manual. Unify its name, calling it as "Kernel API Manual". Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <000e1174a551e97ad4710ad4f3750b22017bedd5.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index d0b237c09391..24ee1fad681e 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -607,20 +607,17 @@ class ManFormat(OutputFormat): "%m %d %Y", ] - def emit_th(self, name, modulename = None, manual=None): + def emit_th(self, name, modulename = None): """Emit a title header line.""" name = name.strip() - if not manual: - manual = self.manual - if not modulename: modulename = self.modulename self.data += f'.TH "{modulename}" {self.section} "{name}" ' - self.data += f'"{self.date}" "{manual}"\n' + self.data += f'"{self.date}" "{self.manual}"\n' - def __init__(self, modulename, section="9", manual="API Manual"): + def __init__(self, modulename, section="9", manual="Kernel API Manual"): """ Creates class variables. @@ -751,8 +748,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.emit_th(out_name, modulename = name, - manual="Kernel Hacker\'s Manual") + self.emit_th(out_name, modulename = name) self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" From 1a63342a2774c734b73841fdfa41cf4d8d58cd94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:44 +0100 Subject: [PATCH 051/162] docs: kdoc_output: don't use a different modulename for functions It doesn't make much sense to have a different modulename just for functions, but not for structs/enums/... Use the same header everywere. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <978259bdf3e8d310c646ecf76ce56d054f6d5738.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 24ee1fad681e..62e300e65405 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -607,14 +607,11 @@ class ManFormat(OutputFormat): "%m %d %Y", ] - def emit_th(self, name, modulename = None): + def emit_th(self, name): """Emit a title header line.""" name = name.strip() - if not modulename: - modulename = self.modulename - - self.data += f'.TH "{modulename}" {self.section} "{name}" ' + self.data += f'.TH "{self.modulename}" {self.section} "{name}" ' self.data += f'"{self.date}" "{self.manual}"\n' def __init__(self, modulename, section="9", manual="Kernel API Manual"): @@ -748,7 +745,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.emit_th(out_name, modulename = name) + self.emit_th(out_name) self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" From 4160533d058cfa667159e8d6a46fe42c738a4a84 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:45 +0100 Subject: [PATCH 052/162] docs: kdoc_output: fix naming for DOC markups Right now, DOC markups aren't being handled properly, as it was using the same name for all output. Fix it by filling the title argument on a different way. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <11d809e5c4bec23240d3ace3f342dbb2a9263446.1772810752.git.mchehab+huawei@kernel.org> --- tools/docs/sphinx-build-wrapper | 2 +- tools/lib/python/kdoc/kdoc_output.py | 38 +++++++++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper index d3f0dba13da1..2c63d28f639d 100755 --- a/tools/docs/sphinx-build-wrapper +++ b/tools/docs/sphinx-build-wrapper @@ -625,7 +625,7 @@ class SphinxBuilder: # Use shlex here, as it handles well parameters with commas args = shlex.split(line) - fname = f"{args[3]}.{args[2]}" + fname = f"{args[1]}.{args[2]}" fname = fname.replace("/", " ") fname = f"{output_dir}/{fname}" diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 62e300e65405..cf834dbf2725 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -607,14 +607,21 @@ class ManFormat(OutputFormat): "%m %d %Y", ] - def emit_th(self, name): + def modulename(self, args): + if self._modulename: + return self._modulename + + return os.path.dirname(args.fname) + + def emit_th(self, name, args): """Emit a title header line.""" - name = name.strip() + title = name.strip() + module = self.modulename(args) - self.data += f'.TH "{self.modulename}" {self.section} "{name}" ' - self.data += f'"{self.date}" "{self.manual}"\n' + self.data += f'.TH "{name}" {self.section} "{self.date}" ' + self.data += f'"{self.modulename}" "{self.manual}"\n' - def __init__(self, modulename, section="9", manual="Kernel API Manual"): + def __init__(self, modulename=None, section="9", manual="Kernel API Manual"): """ Creates class variables. @@ -624,7 +631,7 @@ class ManFormat(OutputFormat): super().__init__() - self.modulename = modulename + self._modulename = modulename self.section = section self.manual = manual @@ -658,7 +665,8 @@ class ManFormat(OutputFormat): dtype = args.type if dtype == "doc": - return self.modulename + return name +# return os.path.basename(self.modulename(args)) if dtype in ["function", "typedef"]: return name @@ -735,7 +743,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.emit_th(out_name) + self.emit_th(out_name, args) for section, text in args.sections.items(): self.data += f'.SH "{section}"' + "\n" @@ -745,7 +753,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) - self.emit_th(out_name) + self.emit_th(out_name, args) self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" @@ -791,7 +799,7 @@ class ManFormat(OutputFormat): def out_enum(self, fname, name, args): out_name = self.arg_name(args, name) - self.emit_th(out_name) + self.emit_th(out_name, args) self.data += ".SH NAME\n" self.data += f"enum {name} \\- {args['purpose']}\n" @@ -824,7 +832,7 @@ class ManFormat(OutputFormat): out_name = self.arg_name(args, name) full_proto = args.other_stuff["full_proto"] - self.emit_th(out_name) + self.emit_th(out_name, args) self.data += ".SH NAME\n" self.data += f"{name} \\- {args['purpose']}\n" @@ -841,11 +849,11 @@ class ManFormat(OutputFormat): self.output_highlight(text) def out_typedef(self, fname, name, args): - module = self.modulename + module = self.modulename(args) purpose = args.get('purpose') out_name = self.arg_name(args, name) - self.emit_th(out_name) + self.emit_th(out_name, args) self.data += ".SH NAME\n" self.data += f"typedef {name} \\- {purpose}\n" @@ -855,12 +863,12 @@ class ManFormat(OutputFormat): self.output_highlight(text) def out_struct(self, fname, name, args): - module = self.modulename + module = self.modulename(args) purpose = args.get('purpose') definition = args.get('definition') out_name = self.arg_name(args, name) - self.emit_th(out_name) + self.emit_th(out_name, args) self.data += ".SH NAME\n" self.data += f"{args.type} {name} \\- {purpose}\n" From 26b4fdefc0f96b1e2e25e0482de1476d037ad325 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:46 +0100 Subject: [PATCH 053/162] docs: kdoc_output: describe the class init parameters As this class is part of the ABI used by both Sphinx kerneldoc extension and docs/tools/kernel-doc, better describe what parmeters are used to initialize ManOutput class. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <7c57f26150aae11fced259f30898a980b96efb68.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 29 +++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index cf834dbf2725..7a181b40810d 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -580,7 +580,34 @@ class RestFormat(OutputFormat): class ManFormat(OutputFormat): - """Consts and functions used by man pages output.""" + """ + Consts and functions used by man pages output. + + This class has one mandatory parameter and some optional ones, which + are needed to define the title header contents: + + ``modulename`` + Defines the module name to be used at the troff ``.TH`` output. + + This argument is mandatory. + + ``section`` + Usually a numeric value from 0 to 9, but man pages also accept + some strings like "p". + + Defauls to ``9`` + + ``manual`` + Defaults to ``Kernel API Manual``. + + The above controls the output of teh corresponding fields on troff + title headers, which will be filled like this:: + + .TH "{name}" {section} "{date}" "{modulename}" "{manual}" + + where ``name``` will match the API symbol name, and ``date`` will be + either the date where the Kernel was compiled or the current date + """ highlights = ( (type_constant, r"\1"), From e4dadcf510da846f32aaaad5d5988890cbf6033d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:47 +0100 Subject: [PATCH 054/162] docs: kdoc_output: pick a better default for modulename Instead of placing the same data for modulename for all generated man pages, use the directory from the filename used to produce kernel docs as basis. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <8a5d91c93c0b9b34c2f60e389f4464742804d0d6.1772810752.git.mchehab+huawei@kernel.org> --- tools/docs/kernel-doc | 1 - tools/lib/python/kdoc/kdoc_output.py | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docs/kernel-doc b/tools/docs/kernel-doc index aed09f9a54dd..3a932f95bdf5 100755 --- a/tools/docs/kernel-doc +++ b/tools/docs/kernel-doc @@ -210,7 +210,6 @@ def main(): help="Enable debug messages") parser.add_argument("-M", "-modulename", "--modulename", - default="Kernel API", help="Allow setting a module name at the output.") parser.add_argument("-l", "-enable-lineno", "--enable_lineno", diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 7a181b40810d..c25f80a39cdc 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -589,7 +589,8 @@ class ManFormat(OutputFormat): ``modulename`` Defines the module name to be used at the troff ``.TH`` output. - This argument is mandatory. + This argument is optional. If not specified, it will be filled + with the directory which contains the documented file. ``section`` Usually a numeric value from 0 to 9, but man pages also accept @@ -645,8 +646,8 @@ class ManFormat(OutputFormat): title = name.strip() module = self.modulename(args) - self.data += f'.TH "{name}" {self.section} "{self.date}" ' - self.data += f'"{self.modulename}" "{self.manual}"\n' + self.data += f'.TH "{title}" {self.section} "{self.date}" ' + self.data += f'"{module}" "{self.manual}"\n' def __init__(self, modulename=None, section="9", manual="Kernel API Manual"): """ From cde7c96f88a0fe9ed53e8bb57147b19a725cf097 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:48 +0100 Subject: [PATCH 055/162] docs: kdoc_output: Change the logic to handle man highlight The code inside ManFormat code to output man pages is too simple: it produces very bad results when the content has tables or code blocks. Change the way lines are parsed there to allow adding extra logic to handle some special cases. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <6ae2301a40b3fcb4381dd9dda8c75d14f9616b46.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index c25f80a39cdc..9caffe0d9753 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -755,15 +755,23 @@ class ManFormat(OutputFormat): if isinstance(contents, list): contents = "\n".join(contents) - for line in contents.strip("\n").split("\n"): - line = KernRe(r"^\s*").sub("", line) - if not line: - continue + lines = contents.strip("\n").split("\n") + i = 0 - if line[0] == ".": - self.data += "\\&" + line + "\n" - else: - self.data += line + "\n" + while i < len(lines): + org_line = lines[i] + + line = KernRe(r"^\s*").sub("", org_line) + + if line: + if line[0] == ".": + self.data += "\\&" + line + "\n" + i += 1 + continue + + i += 1 + + self.data += line + "\n" def out_doc(self, fname, name, args): if not self.check_doc(name, args): From 4ec130cff633361c2217d2ba116ae32772087087 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:49 +0100 Subject: [PATCH 056/162] docs: kdoc_output: add a logic to handle tables inside kernel-doc markups specially when DOC is used, it is not uncommon to have tables inside a kernel-doc markup. Add support for simple tables and complex grid tables when output in groff format. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <442ad76442c325044eb9f34a155d5f484341fb35.1772810752.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 130 +++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 9caffe0d9753..7848514a4d22 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -744,6 +744,126 @@ class ManFormat(OutputFormat): return self.data + def emit_table(self, colspec_row, rows): + + if not rows: + return "" + + out = "" + colspec = "\t".join(["l"] * len(rows[0])) + + out += "\n.TS\n" + out += "box;\n" + out += f"{colspec}.\n" + + if colspec_row: + out_row = [] + + for text in colspec_row: + out_row.append(f"\\fB{text}\\fP") + + out += "\t".join(out_row) + "\n_\n" + + for r in rows: + out += "\t".join(r) + "\n" + + out += ".TE\n" + + return out + + def grid_table(self, lines, start): + """ + Ancillary function to help handling a grid table inside the text. + """ + + i = start + 1 + rows = [] + colspec_row = None + + while i < len(lines): + line = lines[i] + + if KernRe(r"^\s*\|.*\|\s*$").match(line): + parts = [] + + for p in line.strip('|').split('|'): + parts.append(p.strip()) + + rows.append(parts) + + elif KernRe(r'^\+\=[\+\=]+\+\s*$').match(line): + if rows and rows[0]: + if not colspec_row: + colspec_row = [""] * len(rows[0]) + + for j in range(0, len(rows[0])): + content = [] + for row in rows: + content.append(row[j]) + + colspec_row[j] = " ".join(content) + + rows = [] + + elif KernRe(r"^\s*\+[-+]+\+.*$").match(line): + pass + + else: + break + + i += 1 + + return i, self.emit_table(colspec_row, rows) + + def simple_table(self, lines, start): + """ + Ancillary function to help handling a simple table inside the text. + """ + + i = start + rows = [] + colspec_row = None + + pos = [] + for m in KernRe(r'\-+').finditer(lines[i]): + pos.append((m.start(), m.end() - 1)) + + i += 1 + while i < len(lines): + line = lines[i] + + if KernRe(r"^\s*[\-]+[ \t\-]+$").match(line): + i += 1 + break + + elif KernRe(r'^[\s=]+$').match(line): + if rows and rows[0]: + if not colspec_row: + colspec_row = [""] * len(rows[0]) + + for j in range(0, len(rows[0])): + content = [] + for row in rows: + content.append(row[j]) + + colspec_row[j] = " ".join(content) + + rows = [] + + else: + row = [""] * len(pos) + + for j in range(0, len(pos)): + start, end = pos[j] + + row[j] = line[start:end].strip() + + rows.append(row) + + i += 1 + + return i, self.emit_table(colspec_row, rows) + def output_highlight(self, block): """ Outputs a C symbol that may require being highlighted with @@ -764,6 +884,16 @@ class ManFormat(OutputFormat): line = KernRe(r"^\s*").sub("", org_line) if line: + if KernRe(r"^\+\-[-+]+\+.*$").match(line): + i, text = self.grid_table(lines, i) + self.data += text + continue + + if KernRe(r"^\-+[ \t]\-[ \t\-]+$").match(line): + i, text = self.simple_table(lines, i) + self.data += text + continue + if line[0] == ".": self.data += "\\&" + line + "\n" i += 1 From 908ae13b1864c05bcde8cfc7127ec147d28f9414 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:50 +0100 Subject: [PATCH 057/162] docs: kdoc_output: add support to handle code blocks It is common to have code blocks inside kernel-doc markups. By default, troff will group all lines altogether, producing a very weird output. If a code block is detected by disabling filling inside code blocks, re-enabling it afterwards. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_output.py | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 7848514a4d22..df9af444da57 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -864,6 +864,65 @@ class ManFormat(OutputFormat): return i, self.emit_table(colspec_row, rows) + def code_block(self, lines, start): + """ + Ensure that code blocks won't be messed up at the output. + + By default, troff join lines at the same paragraph. Disable it, + on code blocks. + """ + + line = lines[start] + + if "code-block" in line: + out = "\n.nf\n" + elif line.startswith("..") and line.endswith("::"): + # + # Handle note, warning, error, ... markups + # + line = line[2:-1].strip().upper() + out = f"\n.nf\n\\fB{line}\\fP\n" + elif line.endswith("::"): + out = line[:-1] + out += "\n.nf\n" + else: + # Just in case. Should never happen in practice + out = "\n.nf\n" + + i = start + 1 + ident = None + + while i < len(lines): + line = lines[i] + + m = KernRe(r"\S").match(line) + if not m: + out += line + "\n" + i += 1 + continue + + pos = m.start() + if not ident: + if pos > 0: + ident = pos + else: + out += "\n.fi\n" + if i > start + 1: + return i - 1, out + else: + # Just in case. Should never happen in practice + return i, out + + if pos >= ident: + out += line + "\n" + i += 1 + continue + + break + + out += "\n.fi\n" + return i, out + def output_highlight(self, block): """ Outputs a C symbol that may require being highlighted with @@ -894,6 +953,11 @@ class ManFormat(OutputFormat): self.data += text continue + if line.endswith("::") or KernRe(r"\.\.\s+code-block.*::").match(line): + i, text = self.code_block(lines, i) + self.data += text + continue + if line[0] == ".": self.data += "\\&" + line + "\n" i += 1 From ab9150972f21c41d4487e5d4b21cea0ecfe0bb94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2026 16:45:51 +0100 Subject: [PATCH 058/162] docs: kdoc_output: better handle lists On several functions, the return values are inside a bullet list. Also, on some places, there are numbered lists as well. Use a troff markup to format them, to avoid placing everything on a single line. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_output.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index df9af444da57..08539dd92cbb 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -963,6 +963,14 @@ class ManFormat(OutputFormat): i += 1 continue + # + # Handle lists + # + line = KernRe(r'^[-*]\s+').sub(r'.IP \[bu]\n', line) + line = KernRe(r'^(\d+|a-z)[\.\)]\s+').sub(r'.IP \1\n', line) + else: + line = ".PP\n" + i += 1 self.data += line + "\n" From 5e6df46dffb32342c4be6deb6f897363f207bf05 Mon Sep 17 00:00:00 2001 From: Ariful Islam Shoikot Date: Tue, 17 Mar 2026 18:06:13 +0600 Subject: [PATCH 059/162] Documentation/mm/hwpoison.rst: fix typos and grammar. Signed-off-by: Ariful Islam Shoikot Signed-off-by: Jonathan Corbet Message-ID: <20260317120614.51046-1-islamarifulshoikat@gmail.com> --- Documentation/mm/hwpoison.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/mm/hwpoison.rst b/Documentation/mm/hwpoison.rst index 483b72aa7c11..71b4b45c3505 100644 --- a/Documentation/mm/hwpoison.rst +++ b/Documentation/mm/hwpoison.rst @@ -38,7 +38,7 @@ To quote the overview comment:: for the mapping from a vma to a process. Since this case is expected to be rare we hope we can get away with this. -The code consists of a the high level handler in mm/memory-failure.c, +The code consists of the high level handler in mm/memory-failure.c, a new page poison bit and various checks in the VM to handle poisoned pages. From 04c612f6d7641dc563e8aac95649be6c888ba7db Mon Sep 17 00:00:00 2001 From: h3288824963 <3288824963@qq.com> Date: Tue, 17 Mar 2026 18:57:11 +0800 Subject: [PATCH 060/162] Documentation: printk: Add section about avoiding lockups Add a section 'Avoiding lockups from excessive printk() use' to printk-basics.rst, explaining the risk of calling printk() in hot paths with legacy consoles and suggesting alternatives. The section covers: - Rate-limited and one-time printing variants - Log level filtering - printk_deferred() for legacy consoles - Porting to nbcon API (preferred solution) - Using tracepoints for permanent debugging This documentation is relevant only for legacy console drivers and !PREEMPT_RT kernels. Suggested-by: Petr Mladek Suggested-by: John Ogness Signed-off-by: h3288824963 <3288824963@qq.com> Reviewed-by: John Ogness Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/core-api/printk-basics.rst | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Documentation/core-api/printk-basics.rst b/Documentation/core-api/printk-basics.rst index 2dde24ca7d9f..48eaff0ce44c 100644 --- a/Documentation/core-api/printk-basics.rst +++ b/Documentation/core-api/printk-basics.rst @@ -103,6 +103,42 @@ For debugging purposes there are also two conditionally-compiled macros: pr_debug() and pr_devel(), which are compiled-out unless ``DEBUG`` (or also ``CONFIG_DYNAMIC_DEBUG`` in the case of pr_debug()) is defined. +Avoiding lockups from excessive printk() use +============================================ + +.. note:: + + This section is relevant only for legacy console drivers (those not + using the nbcon API) and !PREEMPT_RT kernels. Once all console drivers + are updated to nbcon, this documentation can be removed. + +Using ``printk()`` in hot paths (such as interrupt handlers, timer +callbacks, or high-frequency network receive routines) with legacy +consoles (e.g., ``console=ttyS0``) may cause lockups. Legacy consoles +synchronously acquire ``console_sem`` and block while flushing messages, +potentially disabling interrupts long enough to trigger hard or soft +lockup detectors. + +To avoid this: + +- Use rate-limited variants (e.g., ``pr_*_ratelimited()``) or one-time + macros (e.g., ``pr_*_once()``) to reduce message frequency. +- Assign lower log levels (e.g., ``KERN_DEBUG``) to non-essential messages + and filter console output via ``console_loglevel``. +- Use ``printk_deferred()`` to log messages immediately to the ringbuffer + and defer console printing. This is a workaround for legacy consoles. +- Port legacy console drivers to the non-blocking ``nbcon`` API (indicated + by ``CON_NBCON``). This is the preferred solution, as nbcon consoles + offload message printing to a dedicated kernel thread. + +For temporary debugging, ``trace_printk()`` can be used, but it must not +appear in mainline code. See ``Documentation/trace/debugging.rst`` for +more information. + +If more permanent output is needed in a hot path, trace events can be used. +See ``Documentation/trace/events.rst`` and +``samples/trace_events/trace-events-sample.[ch]``. + Function reference ================== From d0eab64faf0c3b5a354a4ff1eff1b86808014559 Mon Sep 17 00:00:00 2001 From: Praveen Kumar Singh Date: Tue, 17 Mar 2026 11:10:32 +0530 Subject: [PATCH 061/162] docs: memory-hotplug: fix typo 'fo' -> 'for' in NODE_ADDED_FIRST_MEMORY description The description of NODE_ADDED_FIRST_MEMORY notification contains a missing 'r' in the word 'for'. Fix the typo. Signed-off-by: Praveen Kumar Singh Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/core-api/memory-hotplug.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/core-api/memory-hotplug.rst b/Documentation/core-api/memory-hotplug.rst index 8fc97c2379de..46b0490f5319 100644 --- a/Documentation/core-api/memory-hotplug.rst +++ b/Documentation/core-api/memory-hotplug.rst @@ -96,7 +96,7 @@ NODE_CANCEL_ADDING_FIRST_MEMORY Generated if NODE_ADDING_FIRST_MEMORY fails. NODE_ADDED_FIRST_MEMORY - Generated when memory has become available fo this node for the first time. + Generated when memory has become available for this node for the first time. NODE_REMOVING_LAST_MEMORY Generated when the last memory available to this node is about to be offlined. From 9b4e099c221cd118b9dbe720586c1f1c71666d09 Mon Sep 17 00:00:00 2001 From: Ricardo Ungerer Date: Mon, 16 Mar 2026 22:02:17 +0000 Subject: [PATCH 062/162] jobserver: Fix typo in docstring This commit fixes small typos in the docstring of jobserver.py. Signed-off-by: Ricardo Ungerer Signed-off-by: Jonathan Corbet Message-ID: <20260316220218.568022-1-ungerer.ricardo@gmail.com> --- tools/lib/python/jobserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/jobserver.py b/tools/lib/python/jobserver.py index aba22c33393d..0b1ffdf9f7a3 100755 --- a/tools/lib/python/jobserver.py +++ b/tools/lib/python/jobserver.py @@ -8,14 +8,14 @@ """ Interacts with the POSIX jobserver during the Kernel build time. -A "normal" jobserver task, like the one initiated by a make subrocess would do: +A "normal" jobserver task, like the one initiated by a make subprocess would do: - open read/write file descriptors to communicate with the job server; - ask for one slot by calling:: claim = os.read(reader, 1) - - when the job finshes, call:: + - when the job finishes, call:: os.write(writer, b"+") # os.write(writer, claim) From 6f600f9972d56a5d67fcb8d49b33dda80adff457 Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Thu, 12 Mar 2026 17:53:40 +0000 Subject: [PATCH 063/162] docs: interconnect: Add provider APIs to documentation The "Interconnect providers" section currently only includes data structures from include/linux/interconnect-provider.h. Include drivers/interconnect/core.c to extract provider-specific API documentation. The :functions: directive is used to prevent mixing with consumer APIs. Signed-off-by: Kuan-Wei Chiu Signed-off-by: Jonathan Corbet Message-ID: <20260312175341.2944154-2-visitorckw@gmail.com> --- Documentation/driver-api/interconnect.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst index a92d0f277a1f..cf7a83f8c953 100644 --- a/Documentation/driver-api/interconnect.rst +++ b/Documentation/driver-api/interconnect.rst @@ -84,6 +84,12 @@ be registered with the interconnect provider core. .. kernel-doc:: include/linux/interconnect-provider.h +.. kernel-doc:: drivers/interconnect/core.c + :functions: icc_provider_init icc_provider_register icc_provider_deregister + icc_node_create icc_node_create_dyn icc_node_destroy + icc_node_add icc_node_del icc_nodes_remove icc_node_set_name + icc_link_create icc_link_nodes + Interconnect consumers ---------------------- From 97b5266dac802feb34ae45936b73596a7e27d41b Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Thu, 12 Mar 2026 17:53:41 +0000 Subject: [PATCH 064/162] docs: interconnect: Document consumer APIs and drop outdated text The documentation currently states that consumer interfaces are not documented, which is no longer true. Remove the outdated claim and include the existing kernel-doc from drivers/interconnect/core.c (filtered for consumer APIs) and drivers/interconnect/bulk.c. Signed-off-by: Kuan-Wei Chiu Signed-off-by: Jonathan Corbet Message-ID: <20260312175341.2944154-3-visitorckw@gmail.com> --- Documentation/driver-api/interconnect.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst index cf7a83f8c953..cebb77b49d8d 100644 --- a/Documentation/driver-api/interconnect.rst +++ b/Documentation/driver-api/interconnect.rst @@ -95,8 +95,14 @@ Interconnect consumers Interconnect consumers are the clients which use the interconnect APIs to get paths between endpoints and set their bandwidth/latency/QoS requirements -for these interconnect paths. These interfaces are not currently -documented. +for these interconnect paths. + +.. kernel-doc:: drivers/interconnect/core.c + :functions: devm_of_icc_get of_icc_get_by_index of_icc_get icc_get + icc_put icc_enable icc_disable icc_set_bw icc_set_tag + icc_get_name + +.. kernel-doc:: drivers/interconnect/bulk.c Interconnect debugfs interfaces ------------------------------- From c991b7ef2fb658c186df56d16b3ebcd0afb555cc Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Thu, 12 Mar 2026 09:24:24 -0300 Subject: [PATCH 065/162] docs: pt_BR: add netdev and maintainer handbook translations Add the Brazilian Portuguese translation for the netdev subsystem process and update the maintainer handbook to include it. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260312122425.19577-1-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../pt_BR/process/maintainer-handbooks.rst | 11 +- .../pt_BR/process/maintainer-netdev.rst | 596 ++++++++++++++++++ 3 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 Documentation/translations/pt_BR/process/maintainer-netdev.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index de5c005f91d6..8822e21cf463 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -69,3 +69,4 @@ kernel e sobre como ver seu trabalho integrado. Como começar Requisitos mínimos Manuais dos mantenedores + Processo do subsistema de rede (netdev) diff --git a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst index eb650bc6006c..20bb32490303 100644 --- a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst +++ b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst @@ -5,4 +5,13 @@ Notas sobre o processo de desenvolvimento de subsistemas e mantenedores O propósito deste documento é fornecer informações específicas de subsistemas que são suplementares ao manual geral do processo de -desenvolvimento :ref:`Documentation/process `. +desenvolvimento. + +Conteúdos: + +.. toctree:: + :numbered: + :maxdepth: 2 + + maintainer-netdev + diff --git a/Documentation/translations/pt_BR/process/maintainer-netdev.rst b/Documentation/translations/pt_BR/process/maintainer-netdev.rst new file mode 100644 index 000000000000..5de2828041b9 --- /dev/null +++ b/Documentation/translations/pt_BR/process/maintainer-netdev.rst @@ -0,0 +1,596 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================================== +Subsistema de Rede do Linux (netdev) +===================================== + +tl;dr +----- + +- **Direcione seu patch para uma árvore** – use ``[PATCH net]``para correções + ou ``[PATCH net-next]`` para novas funcionalidades. +- **Tag Fixes** – para correções, a tag ``Fixes:`` é obrigatória, + independentemente da árvore de destino. +- **Tamanho da série** – não envie séries grandes (> 15 patches);divida-as em + partes menores. +- **Intervalo de envio** – não reenvie seus patches dentro de um período de 24 + horas. +- **Reverse xmas tree** – organize as declarações de variáveis locais da mais + longa para a mais curta. + +netdev +------ +A **netdev** é a lista de discussão para todos os assuntos do Linux relacionados +a rede. Isso inclui qualquer item encontrado em ``net/`` (ex: código principal +como IPv6) e em ``drivers/net`` (ex: drivers específicos de hardware) na árvore +de diretórios do Linux. + +Note que alguns subsistemas (ex: drivers de rede sem fio/wireless), que possuem +um alto volume de tráfego, possuem suas próprias listas de discussão e árvores +específicas. + +Como muitas outras listas de discussão do Linux, a lista netdev é hospedada no +`kernel.org `_, com arquivos disponíveis em +https://lore.kernel.org/netdev/. + +À exceção dos subsistemas mencionados anteriormente, todo o desenvolvimento de +rede do Linux (ex: RFCs, revisões, comentários, etc.) ocorre na **netdev**. + +Ciclo de Desenvolvimento +------------------------ + +Aqui está um pouco de informação contextual sobre a cadência de desenvolvimento +do Linux. Cada nova versão (release) inicia-se com uma "janela de mesclagem" +(*merge window*) de duas semanas, onde os mantenedores principais enviam suas +novas implementações para o Linus para incorporação na árvore principal +(*mainline tree*). + +Após as duas semanas, a janela de mesclagem é fechada e a versão é +nomeada/etiquetada como ``-rc1``. Nenhuma funcionalidade nova é incorporada à +árvore principal após isso -- espera-se apenas correções (*fixes*) para o +conteúdo da rc1. + +Após cerca de uma semana coletando correções para a rc1, a rc2 é lançada. Isso +se repete semanalmente até a rc7 (tipicamente; às vezes rc6 se o ritmo estiver +calmo, ou rc8 se houver muita instabilidade); uma semana após a última vX.Y-rcN +ser concluída, a versão oficial vX.Y é lançada. + +Para descobrir em que ponto do ciclo estamos agora - carregue a página da +mainline (Linus) aqui: + + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + +e observe o topo da seção de "tags". Se for rc1, estamos no início do ciclo +de desenvolvimento. Se a rc7 foi marcada há uma semana, então um lançamento +é provavelmente iminente. Se a tag mais recente for uma tag de lançamento +final (sem o sufixo ``-rcN``) - muito provavelmente estamos em uma janela de +mesclagem (*merge window*) e o ``net-next`` está fechado. + +Árvores git e fluxo de patches +------------------------------ + +Existem duas árvores de rede (repositórios git) em jogo. Ambas são coordenadas +por David Miller, o mantenedor principal de rede. Há a árvore ``net``e a árvore +``net-next``. Como você provavelmente pode adivinhar pelos nomes, a árvore +``net`` é para correções de código existente já na árvore mainline de Linus, e a +``net-next`` é para onde o novo código vai para o lançamento futuro. +Você pode encontrar as árvores aqui: + +- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git +- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git + +Relacionando isso ao desenvolvimento do kernel: no início da janela de mesclagem +(*merge window*) de 2 semanas, a árvore ``net-next`` será fechada, sem novas +mudanças ou funcionalidades. O conteúdo novo acumulado nas últimas 10 semanas +será passado para a mainline/Linus via um *pull request* para a vX.Y ao mesmo +tempo, a árvore ``net`` começará a acumular correções para este conteúdo enviado +relacionado à vX.Y. + +Um anúncio indicando quando a ``net-next`` foi fechada é geralmente enviado para +a netdev, mas sabendo o que foi dito acima, você pode prever isso com +antecedência. + +.. warning:: + + Não envie novo conteúdo para a ``net-next`` para a netdev durante o período + em que a árvore ``net-next`` estiver fechada. + +Patches RFC enviados apenas para revisão são obviamente bem-vindos a qualquer +momento (use ``--subject-prefix='RFC net-next'`` com ``git format-patch``). + +Pouco depois das duas semanas terem passado (e a vX.Y-rc1 ser lançada), a árvore +para a ``net-next`` reabre para coletar conteúdo para o próximo lançamento +(vX.Y+1). + +Se você não estiver inscrito na netdev e/ou simplesmente não tiver certeza se a +``net-next`` já reabriu, basta verificar o link do repositório git da +``net-next`` acima para quaisquer novos *commits* relacionados à rede. Você +também pode verificar o seguinte site para o status atual: + + https://netdev.bots.linux.dev/net-next.html + +A árvore ``net`` continua a coletar correções para o conteúdo da vX.Y e é +enviada de volta para Linus em intervalos regulares (~semanais). Isso significa +que o foco da ``net`` é a estabilização e correções de bugs. + +Finalmente, a vX.Y é lançada e todo o ciclo recomeça. + +Revisão de patches da netdev +---------------------------- + +Status do patch +~~~~~~~~~~~~~~~ + +O status de um patch pode ser verificado olhando a fila principal do patchwork +para a netdev: + + https://patchwork.kernel.org/project/netdevbpf/list/ + +O campo "State" informará exatamente onde as coisas estão com o seu patch: + +================= ============================================================ +Estado do patch Descrição +================= ============================================================ +New, Under review revisão pendente, o patch está na fila do mantenedor + para revisão; os dois estados são usados alternadamente + (dependendo do co-mantenedor exato que estiver lidando + com o patchwork no momento) +Accepted o patch foi aplicado à árvore de rede apropriada, + isso é geralmente definido de forma automática pelo pw-bot +Needs ACK aguardando um "ack" de um especialista da área + ou testes +Changes requested o patch não passou na revisão, espera-se uma nova + revisão com mudanças apropriadas no código e na mensagem + de commit +Rejected o patch foi rejeitado e não se espera uma nova + revisão +Not applicable espera-se que o patch seja aplicado fora do + subsistema de rede +Awaiting upstream o patch deve ser revisado e tratado pelo sub-mantenedor + apropriado, que o enviará para as árvores de rede; + patches definidos como ``Awaiting upstream`` no patchwork + da netdev geralmente permanecerão neste estado, + independentemente de o sub-mantenedor ter solicitado + mudanças, aceito ou rejeitado o patch +Deferred o patch precisa ser reenviado mais tarde, geralmente + devido a alguma dependência ou porque foi enviado para + uma árvore fechada +Superseded uma nova versão do patch foi enviada, geralmente + definido pelo pw-bot +RFC não deve ser aplicado, geralmente não está na + fila de revisão do mantenedor; o pw-bot pode definir + patches para este estado automaticamente com base nas + tags do assunto +================= ============================================================ + +Os patches são indexados pelo cabeçalho ``Message-ID`` dos e-mails que os +transportaram; portanto, se você tiver problemas para encontrar seu patch, +anexe o valor do ``Message-ID`` à URL acima. + +Atualizando o status do patch +----------------------------- + +Colaboradores e revisores não têm permissões para atualizar o estado do patch +diretamente no patchwork. O Patchwork não expõe muitas informações sobre o +histórico do estado dos patches; portanto, ter várias pessoas atualizando o +estado leva a confusões. + +Em vez de delegar permissões do patchwork, a netdev usa um robô de e-mail +simples (bot) que procura por comandos/linhas especiais dentro dos e-mails +enviados para a lista de discussão. Por exemplo, para marcar uma série como +Mudanças Solicitadas (*Changes Requested*), é necessário enviar a seguinte +linha em qualquer lugar na thread do e-mail:: + + pw-bot: changes-requested + +Como resultado, o bot definirá toda a série como Mudanças Solicitadas. Isso +pode ser útil quando o autor descobre um bug em sua própria série e deseja +evitar que ela seja aplicada. + +O uso do bot é totalmente opcional; em caso de dúvida, ignore completamente a +existência dele. Os mantenedores classificarão e atualizarão o estado dos +patches por conta própria. Nenhum e-mail deve ser enviado à lista com o +propósito principal de se comunicar com o bot; os comandos do bot devem ser +vistos como metadados. + +O uso do bot é restrito aos autores dos patches (o cabeçalho ``From:`` no envio +do patch e no comando deve coincidir!), mantenedores do código modificado de +acordo com o arquivo MAINTAINERS (novamente, o ``From:`` deve coincidir +com a entrada no MAINTAINERS) e alguns revisores seniores. + +O bot registra sua atividade aqui: + + https://netdev.bots.linux.dev/pw-bot.html + +Prazos de revisão +~~~~~~~~~~~~~~~~~ + +De modo geral, os patches são triados rapidamente (em menos de 48h). Mas +seja paciente; se o seu patch estiver ativo no patchwork (ou seja, listado +na lista de patches do projeto), as chances de ele ter sido esquecido são +próximas de zero. + +O alto volume de desenvolvimento na netdev faz com que os revisores encerrem +discussões de forma relativamente rápida. É muito improvável que novos +comentários e respostas cheguem após uma semana de silêncio. Se um +patch não estiver mais ativo no patchwork e a thread ficar inativa por mais de +uma semana - esclareça os próximos passos e/ou envie a próxima versão. + +Especificamente para envios de RFC, se ninguém responder em uma semana ou os +revisores perderam o envio ou não têm opiniões fortes a respeito. Se o código +estiver pronto, reenvie como um PATCH. + +E-mails dizendo apenas "ping" ou "bump" são considerados rudes. Se você não +conseguir identificar o status do patch pelo patchwork ou onde a discussão +parou - descreva sua melhor suposição e pergunte se ela está correta. Por +exemplo:: + + Não entendo quais são os próximos passos. A Pessoa X parece estar descontente + com A; devo fazer B e enviar novamente os patches? + +.. _Solicitações de mudanças: + +Mudanças solicitadas +~~~~~~~~~~~~~~~~~~~~ + +Patches marcados como ``Changes Requested`` precisam ser revisados. A nova +versão deve vir com um registro de alterações (changelog), +preferencialmente incluindo links para as postagens anteriores, por exemplo:: + + [PATCH net-next v3] net: faz as vacas dizerem "muuu" + + Mesmo os usuários que não bebem leite apreciam ouvir as vacas dizendo + "muuu". + + A quantidade de mugidos dependerá da taxa de pacotes, portanto, deve + corresponder muito bem ao ciclo diurno. + + Signed-off-by: Joe Defarmer + --- + v3: + - adicionada uma nota sobre a flutuação do mugido conforme a hora + do dia na + mensagem de commit + v2: https://lore.kernel.org/netdev/123themessageid@barn.org/ + - corrigido argumento ausente na kernel doc para netif_is_bovine() + - corrigido vazamento de memória (memory leak) em + netdev_register_cow() + v1: https://lore.kernel.org/netdev/456getstheclicks@barn.org/ + +A mensagem de commit deve ser revisada para responder a quaisquer perguntas que +os revisores tenham feito em discussões anteriores. Ocasionalmente, a +atualização da mensagem de commit será a única mudança na nova versão. + +Reenvios parciais +~~~~~~~~~~~~~~~~~ + +Por favor, sempre reenvie a série completa de patches e certifique-se de +numerar seus patches de forma que fique claro que este é o conjunto mais +recente e completo de patches que pode ser aplicado. Não tente reenviar apenas +os patches que foram alterados. + +Lidando com patches aplicados incorretamente +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ocasionalmente, uma série de patches é aplicada antes de receber feedback +crítico, ou a versão errada de uma série é aplicada. + +Não é possível fazer o patch desaparecer uma vez que ele foi enviado (pushed); +o histórico de commits nas árvores netdev é imutável. Por favor, envie versões +incrementais sobre o que foi mesclado para corrigir os patches da maneira que +eles ficariam se a sua série de patches mais recente fosse mesclada. + +Em casos onde uma reversão completa (revert) é necessária, a reversão deve ser +enviada como um patch para a lista com uma mensagem de commit explicando os +problemas técnicos com o commit revertido. Reversões devem ser usadas como +último recurso, quando a mudança original está completamente errada; correções +incrementais são preferidas. + +Árvore estável +~~~~~~~~~~~~~~ + +Embora antigamente as submissões para a netdev não devessem carregar tags +explícitas ``CC: stable@vger.kernel.org``, esse não é mais o caso hoje em dia. +Por favor, siga as regras padrão de estabilidade em +``Documentation/process/stable-kernel-rules.rst``, e certifique-se de incluir as +tags Fixes apropriadas! + +Correções de segurança +~~~~~~~~~~~~~~~~~~~~~~ + +Não envie e-mails diretamente para os mantenedores da netdev se você acha que +descobriu um bug que possa ter possíveis implicações de segurança. O atual +mantenedor da netdev tem solicitado consistentemente que as pessoas usem as +listas de discussão e não entrem em contato diretamente. Se você não estiver +de acordo com isso, considere enviar um e-mail para security@kernel.org ou +ler sobre http://oss-security.openwall.org/wiki/mailing-lists/distros como +possíveis mecanismos alternativos. + +Envio conjunto de mudanças em componentes de espaço do usuário +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +O código de espaço do usuário (*user space*) que exercita funcionalidades do +kernel deve ser enviado juntamente com os patches do kernel. Isso dá aos +revisores a chance de ver como qualquer nova interface é usada e quão +bem ela funciona. + +Quando as ferramentas de espaço do usuário residem no próprio repositório do +kernel, todas as alterações devem geralmente vir em uma única série. Se a série +se tornar muito grande ou se o projeto de espaço do usuário não for revisado na +netdev, inclua um link para um repositório público onde os patches de espaço do +usuário possam ser vistos. + +No caso de ferramentas de espaço do usuário residirem em um repositório +separado, mas serem revisadas na netdev (por exemplo, patches para ferramentas +``iproute2``), os patches do kernel e do espaço do usuário devem formar séries +(threads) separadas quando postados na lista de discussão, por exemplo:: + + [PATCH net-next 0/3] net: carta de apresentação de alguma funcionalidade + └─ [PATCH net-next 1/3] net: preparação para alguma funcionalidade + └─ [PATCH net-next 2/3] net: implementação de alguma funcionalidade + └─ [PATCH net-next 3/3] selftest: net: alguma funcionalidade + + [PATCH iproute2-next] ip: adiciona suporte para alguma funcionalidade + +A postagem em uma única thread é desencorajada porque confunde o patchwork +(a partir da versão 2.2.2 do patchwork). + +Envio conjunto de selftests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Os selftests devem fazer parte da mesma série que as mudanças de código. +Especificamente para correções, tanto a mudança de código quanto o teste +relacionado devem ir para a mesma árvore (os testes podem não ter uma tag +Fixes, o que é esperado). Misturar mudanças de código e mudanças de teste em +um único commit é desencorajado. + +Preparando as mudanças +---------------------- + +Atenção aos detalhes é importante. Releia seu próprio trabalho como se você +fosse o revisor. Você pode começar usando o ``checkpatch.pl``, talvez até com +a flag ``--strict``. Mas não seja robótico e irracional ao fazer isso. Se sua +mudança for uma correção de bug, certifique-se de que seu log de commit indique +o sintoma visível para o usuário final, a razão subjacente de por que isso +acontece e, se necessário, explique por que a correção proposta é a melhor +maneira de resolver as coisas. Não corrompa espaços em branco e, como é comum, +não use recuos incorretos em argumentos de função que abrangem várias linhas. +Se for o seu primeiro patch, envie-o para si mesmo por e-mail para que você +possa testar a aplicação em uma árvore sem patches para confirmar que a +infraestrutura não o danificou. + +Finalmente, volte e leia ``Documentation/process/submitting-patches.rst`` +para ter certeza de que não está repetindo algum erro comum documentado lá. + +Indicando a árvore de destino +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Para ajudar os mantenedores e os bots de CI, você deve marcar explicitamente +qual árvore seu patch tem como alvo. Supondo que você use git, utilize a flag +de prefixo:: + + git format-patch --subject-prefix='PATCH net-next' inicio..fim + +Use ``net`` em vez de ``net-next`` (sempre em letras minúsculas) no comando +acima para conteúdos de correção de bugs da árvore ``net``. + +Dividindo o trabalho em patches +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Coloque-se no lugar do revisor. Cada patch é lido separadamente e, portanto, +deve constituir um passo compreensível em direção ao seu objetivo declarado. + +Evite enviar séries com mais de 15 patches. Séries maiores levam mais tempo +para serem revisadas, pois os revisores adiarão a análise até encontrarem um +grande bloco de tempo disponível. Uma série pequena pode ser revisada em pouco +tempo, então os mantenedores simplesmente a revisam de imediato. Como resultado, +uma sequência de séries menores é mesclada mais rapidamente e com melhor +cobertura de revisão. Reenviar séries grandes também aumenta o tráfego na lista +de discussão. + +Limitar patches pendentes na lista de discussão +----------------------------------------------- + +Evite ter mais de 15 patches, em todas as séries, pendentes de revisão na lista +de discussão para uma única árvore. Em outras palavras, um máximo de 15 patches +sob revisão na ``net`` e um máximo de 15 patches sob revisão na ``net-next``. + +Este limite tem o objetivo de focar o esforço do desenvolvedor nos testes dos +patches antes da revisão upstream, auxiliando a qualidade das submissões +upstream e aliviando a carga sobre os revisores. + +Ordenação de variáveis locais ("árvore invertida", "RCS") +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A netdev tem uma convenção para ordenar variáveis locais em funções. Ordene as +linhas de declaração de variáveis da mais longa para a mais curta, por exemplo:: + + struct scatterlist *sg; + struct sk_buff *skb; + int err, i; + +Se houver dependências entre as variáveis que impeçam a ordenação, mova a +inicialização para fora da linha de declaração. + +Precedência de formatação +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ao trabalhar em código existente que utiliza formatação não padrão, faça com +que seu código siga as diretrizes mais recentes, para que, eventualmente, +todo o código no domínio da netdev esteja no formato preferido. + +Uso de construções gerenciadas por dispositivo e cleanup.h +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Historicamente, a netdev permanece cética em relação às promessas de todas as +APIs de "auto-limpeza" (auto-cleanup), incluindo até mesmo os auxiliares +``devm_``. Eles não são o estilo preferido de implementação, apenas um estilo +aceitável. + +O uso de ``guard()`` é desencorajado em qualquer função com mais de 20 linhas; +``scoped_guard()`` é considerado mais legível. O uso de lock/unlock normal +ainda é (levemente) preferido. + +Construções de limpeza de baixo nível (como ``__free()``) podem ser usadas ao +construir APIs e auxiliares, especialmente iteradores com escopo. No entanto, o +uso direto de ``__free()`` dentro do núcleo de rede (networking core) e drivers +é desencorajado. Orientações semelhantes se aplicam à declaração de variáveis +no meio da função. + +Patches de limpeza (Clean-up patches) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A netdev desencoraja patches que realizam limpezas simples que não estejam no +contexto de outro trabalho. Por exemplo: + +* Tratar avisos do ``checkpatch.pl`` e outros avisos triviais de estilo de + codificação +* Tratar problemas de Ordenação de variáveis locais +* Conversões para APIs gerenciadas por dispositivo (auxiliares ``devm_``) + +Isso ocorre porque se considera que a agitação (*churn*) que tais mudanças +produzem tem um custo maior do que o valor de tais limpezas. + +Por outro lado, correções de ortografia e gramática não são desencorajadas. + +Reenviando após a revisão +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Aguarde pelo menos 24 horas entre as postagens. Isso garantirá que revisores de +todas as localizações geográficas tenham a chance de se manifestar. Não espere +muito tempo (semanas) entre as postagens, pois isso tornará mais difícil para +os revisores lembrarem de todo o contexto. + +Certifique-se de tratar todo o feedback em sua nova postagem. Não envie uma +nova versão do código se a discussão sobre a versão anterior ainda estiver em +andamento, a menos que seja instruído diretamente por um revisor. + +A nova versão dos patches deve ser postada como uma thread separada, não como +uma resposta à postagem anterior. O registro de alterações (changelog) deve +incluir um link para a postagem anterior (veja :ref:`Solicitações +de mudanças`). + +Testes +------ + +Nível de teste esperado +~~~~~~~~~~~~~~~~~~~~~~~ + +No mínimo, suas alterações devem passar por uma compilação ``allyesconfig`` e +uma ``allmodconfig`` com ``W=1`` definido, sem novos avisos ou falhas. + +O ideal é que você tenha feito testes em tempo de execução específicos para sua +alteração, e que a série de patches contenha um conjunto de selftests do kernel +para ``tools/testing/selftests/net`` ou usando o framework KUnit. + +Espera-se que você teste suas alterações no topo da árvore de rede relevante +(``net`` ou ``net-next``) e não, por exemplo, em uma árvore estável ou na +``linux-next``. + +Verificações do patchwork +~~~~~~~~~~~~~~~~~~~~~~~~~ + +As verificações (*checks*) no patchwork são, em sua maioria, wrappers simples +em torno de scripts existentes do kernel; as fontes estão disponíveis em: + +https://github.com/linux-netdev/nipa/tree/master/tests + +**Não** envie seus patches apenas para executá-los nas verificações. Você deve +garantir que seus patches estejam prontos, testando-os localmente antes de +postar na lista de discussão. A instância do bot de build do patchwork fica +sobrecarregada com muita facilidade e a netdev@vger realmente não precisa de +mais tráfego se pudermos evitar. + +netdevsim +~~~~~~~~~ + +O ``netdevsim`` é um driver de teste que pode ser usado para exercitar APIs de +configuração de driver sem a necessidade de hardware compatível. Mock-ups e +testes baseados no ``netdevsim`` são fortemente encorajados ao adicionar novas +APIs, mas o ``netdevsim`` em si **não** é considerado um caso de uso/usuário. +Você também deve implementar as novas APIs em um driver real. + +Não damos garantias de que o ``netdevsim`` mudará no futuro de uma forma que +quebraria o que normalmente seria considerado uAPI. O ``netdevsim`` é reservado +apenas para uso por testes upstream, portanto, quaisquer novos recursos do +``netdevsim`` devem ser acompanhados de selftests em ``tools/testing/selftests/``. + +Status de suporte para drivers +------------------------------ + +.. note: + +Os requisitos a seguir aplicam-se apenas a drivers de NIC Ethernet. + +A netdev define requisitos adicionais para drivers que desejam adquirir o status +``Supported`` (Suportado) no arquivo MAINTAINERS. Drivers ``Supported`` devem +executar todos os testes de driver upstream e relatar os resultados duas vezes +por dia. Drivers que não cumprirem este requisito devem usar o status +``Maintained`` (Mantido). Atualmente, não há diferença na forma como os drivers +``Supported`` e ``Maintained`` são tratados no upstream. + +As regras exatas que um driver deve seguir para adquirir o status ``Supported``: + +1. Deve executar todos os testes sob os alvos ``drivers/net`` e + ``drivers/net/hw`` dos selftests do Linux. A execução e o relato + de testes privados / internos também são bem-vindos, mas os testes + upstream são obrigatórios. + +2. A frequência mínima de execução é uma vez a cada 12 horas. Deve + testar o branch designado a partir do feed de branches selecionado. + Observe que os branches são construídos automaticamente e estão + expostos à postagem intencional de patches maliciosos; portanto, + os sistemas de teste devem ser isolados. + +3. Drivers que suportam múltiplas gerações de dispositivos devem + testar pelo menos um dispositivo de cada geração. Um manifesto do + ambiente de teste (*testbed manifest* - formato exato a definir) + deve descrever os modelos de dispositivos testados. + +4. Os testes devem ser executados de forma confiável; se múltiplos + branches forem ignorados ou se os testes falharem devido a problemas + no ambiente de execução, o status ``Supported`` será retirado. + +5. Falhas nos testes devido a bugs no driver ou no próprio teste, + ou falta de suporte para a funcionalidade que o teste visa, *não* + são motivo para a perda do status ``Supported``. + +O CI da netdev manterá uma página oficial de dispositivos suportados, listando +seus resultados de testes recentes. + +O mantenedor do driver pode providenciar para que outra pessoa execute o teste; +não há exigência de que a pessoa listada como mantenedora (ou seu empregador) +seja responsável pela execução dos testes. Colaborações entre +fornecedores, hospedagem de CI no GitHub (GH CI), outros repositórios sob o +linux-netdev, etc., são muito bem-vindas. + +Veja https://github.com/linux-netdev/nipa/wiki para mais informações sobre o CI +da netdev. Sinta-se à vontade para entrar em contato com os mantenedores ou com +a lista para quaisquer dúvidas. + +Orientações para revisores +-------------------------- + +Revisar patches de outras pessoas na lista é altamente incentivado, +independentemente do nível de experiência. Para orientações gerais e dicas +úteis, consulte `revisão de tópicos avançados de desenvolvimento`. + +É seguro assumir que os mantenedores da netdev conhecem a comunidade e o nível +de experiência dos revisores. Os revisores não devem se preocupar com o fato de +seus comentários impedirem ou desviarem o fluxo de patches. Revisores menos +experientes são fortemente incentivados a fazer uma revisão mais aprofundada das +submissões e não focar exclusivamente em questões triviais ou subjetivas, como +formatação de código, tags, etc. + +Depoimentos / feedback +---------------------- + +Algumas empresas utilizam o feedback de colegas em revisões de desempenho de +funcionários. Sinta-se à vontade para solicitar feedback dos mantenedores da +netdev, especialmente se você dedica uma quantidade significativa de tempo +revisando código e se esforça além do esperado para melhorar a infraestrutura +compartilhada. + +O feedback deve ser solicitado por você, o colaborador, e será sempre +compartilhado com você (mesmo que você solicite que ele seja enviado ao seu +gerente). \ No newline at end of file From 98e7b5752898f74788098bef51f53205e365ab9d Mon Sep 17 00:00:00 2001 From: Manuel Ebner Date: Wed, 11 Mar 2026 17:54:41 +0100 Subject: [PATCH 066/162] scripts: ver_linux: expand and fix list It is a pain in the ass to compare the software versions on the running system (scripts/ver_linux) with the minimal required versions. Sorting both lists the same way makes side-by-side comparisons a simple task. fix path to changes.rst make toolnames uniform with the toolnames in Changes.rst make version commands uniform with Changes.rst Add missing tools in ver_linux bash, bc, bindgen, btrfs-progs, Clang, gdb, GNU awk, GNU tar, GRUB, GRUB2, gtags, iptables, kmod, mcelog, mkimage, openssl, pahole, Python, Rust, Sphinx, squashfs-tools Signed-off-by: Manuel Ebner Message-ID: <20260311165440.183672-2-manuelebner@airmail.cc> Signed-off-by: Jonathan Corbet --- scripts/ver_linux | 50 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/scripts/ver_linux b/scripts/ver_linux index d6f2362d3792..458c30a44f8d 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -7,7 +7,7 @@ BEGIN { usage = "If some fields are empty or look unusual you may have an old version.\n" - usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" + usage = usage "Compare to the current minimal requirements in Documentation/process/changes.rst\n" print usage system("uname -a") @@ -18,22 +18,22 @@ BEGIN { libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$" printversion("GNU C", version("gcc -dumpversion")) - printversion("GNU Make", version("make --version")) - printversion("Binutils", version("ld -v")) - printversion("Util-linux", version("mount --version")) + printversion("GNU make", version("make --version")) + printversion("binutils", version("ld -v")) + printversion("util-linux", version("mount --version")) printversion("Mount", version("mount --version")) printversion("Module-init-tools", version("depmod -V")) - printversion("E2fsprogs", version("tune2fs")) - printversion("Jfsutils", version("fsck.jfs -V")) - printversion("Xfsprogs", version("xfs_db -V")) - printversion("Pcmciautils", version("pccardctl -V")) + printversion("e2fsprogs", version("e2fsck -V")) + printversion("jfsutils", version("fsck.jfs -V")) + printversion("xfsprogs", version("xfs_db -V")) + printversion("pcmciautils", version("pccardctl -V")) printversion("Pcmcia-cs", version("cardmgr -V")) - printversion("Quota-tools", version("quota -V")) + printversion("quota-tools", version("quota -V")) printversion("PPP", version("pppd --version")) printversion("Isdn4k-utils", version("isdnctrl")) - printversion("Nfs-utils", version("showmount --version")) - printversion("Bison", version("bison --version")) - printversion("Flex", version("flex --version")) + printversion("nfs-utils", version("showmount --version")) + printversion("bison", version("bison --version")) + printversion("flex", version("flex --version")) while ("ldconfig -p 2>/dev/null" | getline > 0) if ($NF ~ libc || $NF ~ libcpp) @@ -41,13 +41,35 @@ BEGIN { printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver) printversion("Dynamic linker (ldd)", version("ldd --version")) - printversion("Procps", version("ps --version")) + printversion("procps", version("ps --version")) printversion("Net-tools", version("ifconfig --version")) printversion("Kbd", version("loadkeys -V")) printversion("Console-tools", version("loadkeys -V")) printversion("Sh-utils", version("expr --v")) - printversion("Udev", version("udevadm --version")) + printversion("udev", version("udevadm --version")) printversion("Wireless-tools", version("iwconfig --version")) + printversion("bash", version("bash --version")) + printversion("bc", version("bc --version")) + printversion("bindgen", version("bindgen --version")) + printversion("btrfs-progs", version("btrfs --version")) + printversion("Clang", version("clang --version")) + printversion("gdb", version("gdb -version")) + printversion("GNU awk", version("gawk --version")) + printversion("GNU tar", version("tar --version")) + printversion("GRUB", version("grub-install --version")) + printversion("GRUB2", version("grub2-install --version")) + printversion("gtags", version("gtags --version")) + printversion("iptables", version("iptables -V")) + printversion("kmod", version("kmod -V")) + printversion("mcelog", version("mcelog --version")) + printversion("mkimage", version("mkimage --version")) + printversion("openssl", version("openssl version")) + printversion("pahole", version("pahole --version")) + printversion("Python", version("python3 -V")) + printversion("Rust", version("rustc --version")) + printversion("Sphinx", version("sphinx-build --version")) + printversion("squashfs-tools", version("mksquashfs -version")) + while ("sort /proc/modules" | getline > 0) { mods = mods sep $1 From a39b136f67091533cb74829b0090db52089e6400 Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Thu, 19 Mar 2026 08:54:11 -0300 Subject: [PATCH 067/162] docs/pt_BR: translation of maintainer-soc.rst Translate Documentation/process/maintainer-soc.rst into Portuguese. This is part of the effort to localize the kernel documentation. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260319115416.495020-2-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../pt_BR/process/maintainer-handbooks.rst | 1 + .../pt_BR/process/maintainer-soc.rst | 222 ++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 Documentation/translations/pt_BR/process/maintainer-soc.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index 8822e21cf463..d6a28bc5ad08 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -70,3 +70,4 @@ kernel e sobre como ver seu trabalho integrado. Requisitos mínimos Manuais dos mantenedores Processo do subsistema de rede (netdev) + Processo do subsistema SoC diff --git a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst index 20bb32490303..71ea0b9d63a6 100644 --- a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst +++ b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst @@ -14,4 +14,5 @@ Conteúdos: :maxdepth: 2 maintainer-netdev + maintainer-soc diff --git a/Documentation/translations/pt_BR/process/maintainer-soc.rst b/Documentation/translations/pt_BR/process/maintainer-soc.rst new file mode 100644 index 000000000000..5a3ae213ef67 --- /dev/null +++ b/Documentation/translations/pt_BR/process/maintainer-soc.rst @@ -0,0 +1,222 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============== +Subsistema SoC +============== + +Visão Geral +----------- + +O subsistema SoC é um local de agregação para códigos específicos de SoC +System on Chip). Os principais componentes do subsistema são: + +* Devicetrees (DTS) para ARM de 32 e 64 bits e RISC-V. +* Arquivos de placa (board files) ARM de 32 bits (arch/arm/mach*). +* Defconfigs ARM de 32 e 64 bits. +* Drivers específicos de SoC em diversas arquiteturas, em particular para ARM de +* 32 e 64 bits, RISC-V e Loongarch. + +Estes "drivers específicos de SoC" não incluem drivers de clock, GPIO, etc., que +possuem outros mantenedores de alto nível. O diretório ``drivers/soc/`` é +geralmente destinado a drivers internos do kernel que são usados por outros +drivers para fornecer funcionalidades específicas do SoC, como identificar uma +revisão do chip ou fazer a interface com domínios de energia. + +O subsistema SoC também serve como um local intermediário para alterações em +``drivers/bus``, ``drivers/firmware``, ``drivers/reset`` e ``drivers/memory``. +A adição de novas plataformas, ou a remoção de existentes, geralmente passa pela +árvore SoC como um branch dedicado cobrindo múltiplos subsistemas. + +A árvore principal do SoC está hospedada no git.kernel.org: + https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/ + +Mantenedores +------------ + +Claramente, esta é uma gama bastante ampla de tópicos, que nenhuma pessoa, ou +mesmo um pequeno grupo de pessoas, é capaz de manter. Em vez disso, o +subsistema SoC é composto por muitos submantenedores (mantenedores de +plataforma), cada um cuidando de plataformas individuais e subdiretórios de +drivers. + +Nesse sentido, "plataforma" geralmente se refere a uma série de SoCs de um +determinado fornecedor, por exemplo, a série de SoCs Tegra da Nvidia. Muitos +submantenedores operam em nível de fornecedor, sendo responsáveis por várias +linhas de produtos. Por diversos motivos, incluindo aquisições ou diferentes +unidades de negócios em uma empresa, as coisas variam significativamente aqui. +Os diversos submantenedores estão documentados no arquivo ``MAINTAINERS``. + +A maioria desses submantenedores possui suas próprias árvores onde preparam os +patches, enviando pull requests para a árvore SoC principal. Essas árvores são +geralmente, mas nem sempre, listadas em ``MAINTAINERS``. + +O que a árvore SoC não é, contudo, é um local para alterações de código +específicas da arquitetura. Cada arquitetura possui seus próprios mantenedores +que são responsáveis pelos detalhes arquiteturais, erratas de CPU e afins. + +Submetendo Patches para um Determinado SoC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Todos os patches típicos relacionados à plataforma devem ser enviados por meio +dos submantenedores de SoC (mantenedores específicos da plataforma). Isso inclui +também alterações em defconfigs por plataforma ou compartilhadas. Note que +``scripts/get_maintainer.pl`` pode não fornecer os endereços corretos para a +defconfig compartilhada; portanto, ignore sua saída e crie manualmente a lista +de CC baseada no arquivo ``MAINTAINERS`` ou use algo como +``scripts/get_maintainer.pl -f drivers/soc/FOO/``. + +Submetendo Patches para os Mantenedores Principais de SoC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Os mantenedores principais de SoC podem ser contatados via o alias +soc@kernel.org apenas nos seguintes casos: + +1. Não existem mantenedores específicos para a plataforma. + +2. Os mantenedores específicos da plataforma não respondem. + +3. Introdução de uma plataforma SoC completamente nova. Tal trabalho de novo SoC + deve ser enviado primeiro para as listas de discussão comuns, indicadas por + ``scripts/get_maintainer.pl``, para revisão da comunidade. Após uma revisão + positiva da comunidade, o trabalho deve ser enviado para soc@kernel.org em + um único conjunto de patches (*patchset*) contendo a nova entrada em + ``arch/foo/Kconfig``, arquivos DTS, entrada no arquivo ``MAINTAINERS`` e, + opcionalmente, drivers iniciais com seus respectivos bindings de Devicetree. + A entrada no arquivo ``MAINTAINERS`` deve listar os novos mantenedores + específicos da plataforma, que serão responsáveis por lidar com os patches + da plataforma de agora em diante. + +Note que o endereço soc@kernel.org geralmente não é o local para discutir os +patches; portanto, o trabalho enviado para este endereço já deve ser +considerado aceitável pela comunidade. + +Informações para (novos) Submantenedores +---------------------------------------- + +À medida que novas plataformas surgem, elas frequentemente trazem consigo novos +submantenedores, muitos dos quais trabalham para o fornecedor do silício e podem +não estar familiarizados com o processo. + +Estabilidade da ABI do Devicetree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Talvez um dos pontos mais importantes a destacar é que os *dt-bindings* +documentam a ABI entre o devicetree e o kernel. Por favor, leia +``Documentation/devicetree/bindings/ABI.rst``. + +Se estiverem sendo feitas alterações em um DTS que sejam incompatíveis com +kernels antigos, o patch do DTS não deve ser aplicado até que o driver seja, ou +em um momento apropriado posterior. Mais importante ainda, quaisquer alterações +incompatíveis devem ser claramente apontadas na descrição do patch e no pull +request, juntamente com o impacto esperado nos usuários existentes, como +bootloaders ou outros sistemas operacionais. + +Dependências de Branch de Driver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Um problema comum é a sincronização de alterações entre drivers de dispositivos +e arquivos de devicetree. Mesmo que uma alteração seja compatível em ambas as +direções, isso pode exigir a coordenação de como as mudanças são mescladas +através de diferentes árvores de mantenedores. + +Geralmente, o branch que inclui uma alteração de driver também incluirá a +mudança correspondente na descrição do binding do devicetree, para garantir que +sejam, de fato, compatíveis. Isso significa que o branch do devicetree pode +acabar causando avisos na etapa ``make dtbs_check``. Se uma alteração de +devicetree depender de adições ausentes em um arquivo de cabeçalho em +``include/dt-bindings/``, ela falhará na etapa ``make dtbs`` e não será mesclada. + +Existem várias maneiras de lidar com isso: + +* Evite definir macros personalizadas em ``include/dt-bindings/`` para constantes + de hardware que podem ser derivadas de um datasheet -- macros de binding em + arquivos de cabeçalho devem ser usadas apenas como último recurso, se não + houver uma maneira natural de definir um binding. + +* Use valores literais no arquivo devicetree em vez de macros, mesmo quando um + cabeçalho for necessário, e altere-os para a representação nomeada em um + lançamento posterior. + +* Adie as alterações do devicetree para um lançamento após o binding e o driver + já terem sido mesclados. + +* Altere os bindings em um branch imutável compartilhado que seja usado como + base tanto para a alteração do driver quanto para as alterações do devicetree. + +* Adicione definições duplicadas no arquivo devicetree protegidas por uma seção + ``#ifndef``, removendo-as em um lançamento posterior. + +Convenção de Nomenclatura de Devicetree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +O esquema geral de nomenclatura para arquivos de devicetree é o seguinte. Os +aspectos de uma plataforma que são definidos no nível do SoC, como núcleos de +CPU, são contidos em um arquivo nomeado ``$soc.dtsi``, por exemplo, +``jh7100.dtsi``. Detalhes de integração, que variam de placa para placa, são +descritos em ``$soc-$board.dts``. Um exemplo disso é +``jh7100-beaglev-starlight.dts``. Frequentemente, muitas placas são variações +de um mesmo tema, e é comum haver arquivos intermediários, como +``jh7100-common.dtsi``, que ficam entre os arquivos ``$soc.dtsi`` e +``$soc-$board.dts``, contendo as descrições de hardware comum. + +Algumas plataformas também possuem *System on Modules* (SoM), contendo um SoC, +que são então integrados em diversas placas diferentes. Para essas plataformas, +``$soc-$som.dtsi`` e ``$soc-$som-$board.dts`` são típicos. + +Os diretórios geralmente são nomeados após o fornecedor do SoC no momento de sua +inclusão, o que leva a alguns nomes de diretórios históricos na árvore. + +Validando Arquivos de Devicetree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``make dtbs_check`` pode ser usado para validar se os arquivos de devicetree +estão em conformidade com os *dt-bindings* que descrevem a ABI. Por favor, leia +a seção "Running checks" de ``Documentation/devicetree/bindings/writing-schema.rst`` +para mais informações sobre a validação de devicetrees. + +Para novas plataformas, ou adições a plataformas existentes, ``make dtbs_check`` +não deve adicionar nenhum aviso (*warning*) novo. Para SoCs RISC-V e Samsung, é +exigido que ``make dtbs_check W=1`` não adicione nenhum novo aviso. +Se houver qualquer dúvida sobre uma alteração de devicetree, entre em contato +com os mantenedores de devicetree. + +Branches e Pull Requests +~~~~~~~~~~~~~~~~~~~~~~~~ + +Assim como a árvore SoC principal possui vários branches, espera-se que os +submantenedores façam o mesmo. Alterações de drivers, defconfig e devicetree +devem ser todas divididas em branches separados e aparecer em pull requests +distintos para os mantenedores de SoC. Cada branch deve ser utilizável por si só +e evitar regressões originadas de dependências em outros branches. + +Pequenos conjuntos de patches também podem ser enviados como e-mails separados +para soc@kernel.org, agrupados nas mesmas categorias. + +Se as alterações não se encaixarem nos padrões normais, pode haver branches de +nível superior adicionais, por exemplo, para uma reformulação em toda a árvore +(*treewide rework*) ou a adição de novas plataformas SoC, incluindo arquivos dts +e drivers. + +Branches com muitas alterações podem se beneficiar ao serem divididos em +branches de tópicos separados, mesmo que acabem sendo mesclados no mesmo branch +da árvore SoC. Um exemplo aqui seria um branch para correções de avisos de +devicetree, um para uma reformulação e um para placas recém-adicionadas. + +Outra forma comum de dividir as alterações é enviar um pull request antecipado +com a maioria das mudanças em algum momento entre rc1 e rc4, seguido por um ou +mais pull requests menores no final do ciclo, que podem adicionar alterações +tardias ou resolver problemas identificados durante os testes do primeiro +conjunto. + +Embora não haja um prazo limite para pull requests tardios, ajuda enviar apenas +branches pequenos à medida que o tempo se aproxima da janela de mesclagem +(*merge window*). + +Pull requests para correções de bugs (*bugfixes*) da versão atual podem ser +enviados a qualquer momento, mas, novamente, ter múltiplos branches menores é +melhor do que tentar combinar muitos patches em um único pull request. + +A linha de assunto de um pull request deve começar com "[GIT PULL]" e ser feita +usando uma tag assinada, em vez de um branch. Esta tag deve conter uma breve +descrição resumindo as alterações no pull request. Para mais detalhes sobre o +envio de pull requests, consulte ``Documentation/maintainer/pull-requests.rst``. From 98b764fd72bd8a1fe357f0d65bb929ae11efc75b Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Thu, 19 Mar 2026 08:54:12 -0300 Subject: [PATCH 068/162] docs/pt_BR: translation of maintainer-soc-clean-dts.rst Translate Documentation/process/maintainer-soc-clean-dts.rst into Portuguese. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260319115416.495020-3-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../pt_BR/process/maintainer-handbooks.rst | 2 +- .../process/maintainer-soc-clean-dts.rst | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 Documentation/translations/pt_BR/process/maintainer-soc-clean-dts.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index d6a28bc5ad08..86a608ac82ff 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -71,3 +71,4 @@ kernel e sobre como ver seu trabalho integrado. Manuais dos mantenedores Processo do subsistema de rede (netdev) Processo do subsistema SoC + Conformidade de DTS para SoC diff --git a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst index 71ea0b9d63a6..ba36df8eeaf1 100644 --- a/Documentation/translations/pt_BR/process/maintainer-handbooks.rst +++ b/Documentation/translations/pt_BR/process/maintainer-handbooks.rst @@ -15,4 +15,4 @@ Conteúdos: maintainer-netdev maintainer-soc - + maintainer-soc-clean-dts diff --git a/Documentation/translations/pt_BR/process/maintainer-soc-clean-dts.rst b/Documentation/translations/pt_BR/process/maintainer-soc-clean-dts.rst new file mode 100644 index 000000000000..a7e7bf0f106f --- /dev/null +++ b/Documentation/translations/pt_BR/process/maintainer-soc-clean-dts.rst @@ -0,0 +1,28 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================================================== +Plataformas SoC com Requisitos de Conformidade de DTS +===================================================== + +Visão Geral +----------- + +As plataformas SoC ou subarquiteturas devem seguir todas as regras de +Documentation/process/maintainer-soc.rst. Este documento, referenciado em +MAINTAINERS, impõe requisitos adicionais listados abaixo. + +Conformidade Estrita com DT Schema de DTS e dtc +----------------------------------------------- + +Nenhuma alteração nos arquivos de origem do Devicetree da plataforma SoC +(arquivos DTS) deve introduzir novos avisos de ``make dtbs_check W=1``. +Avisos em um novo DTS de placa, que sejam resultado de problemas em um +arquivo DTSI incluído, são considerados avisos existentes, não novos. +Para séries divididas entre árvores diferentes (vínculos de DT seguem pela +árvore do subsistema de drivers), os avisos no linux-next são decisivos. +Os mantenedores da plataforma possuem automação implementada que deve +apontar quaisquer novos avisos. + +Se um commit que introduz novos avisos for aceito de alguma forma, os +problemas resultantes deverão ser corrigidos em um tempo razoável +(por exemplo, dentro de um ciclo de lançamento) ou o commit será revertido. From a0529bbe70d74e495b682933955e5938245ad84b Mon Sep 17 00:00:00 2001 From: Daniel Castro Date: Tue, 17 Mar 2026 11:01:34 -0300 Subject: [PATCH 069/162] docs: pt_BR: translate process/1.Intro.rst Add Brazilian Portuguese translation of the development process introduction (Documentation/process/1.Intro.rst), covering the executive summary, importance of mainline code, and licensing. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Daniel Castro Signed-off-by: Jonathan Corbet Message-ID: <20260317140136.29256-1-arantescastro@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../translations/pt_BR/process/1.Intro.rst | 269 ++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 Documentation/translations/pt_BR/process/1.Intro.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index 86a608ac82ff..a89837aefc3e 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -66,6 +66,7 @@ kernel e sobre como ver seu trabalho integrado. .. toctree:: :maxdepth: 1 + Introdução Como começar Requisitos mínimos Manuais dos mantenedores diff --git a/Documentation/translations/pt_BR/process/1.Intro.rst b/Documentation/translations/pt_BR/process/1.Intro.rst new file mode 100644 index 000000000000..2995fa49e4c4 --- /dev/null +++ b/Documentation/translations/pt_BR/process/1.Intro.rst @@ -0,0 +1,269 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Introdução +========== + +Sumário +------- + +O restante desta seção cobre o processo de desenvolvimento do kernel e os +tipos de frustração que os desenvolvedores e empresas podem encontrar pelo +caminho. Existem diversas razões que justificam a recomendação para que seja +feito o merge do código do kernel ao kernel principal ("mainline"), como +disponibilidade automática aos usuários, suporte da comunidade em diversas +formas, e a oportunidade de influenciar a direção do desenvolvimento do +kernel. Contribuições ao kernel Linux obrigatoriamente devem estar disponíveis +sob uma licença compatível com a GPL. + +:ref:`development_process` apresenta o processo de desenvolvimento, o ciclo de +lançamento, e a mecânica da janela de merge. As várias fases no desenvolvimento +de patch, revisão, e ciclo de merge são explicadas. Algumas ferramentas e +listas de e-mail são discutidas. Desenvolvedores que queiram começar a +desenvolver o kernel são encorajados a buscar e corrigir bugs como exercício +inicial. + +:ref:`development_early_stage` cobre os primeiros passos do processo de +desenvolvimento, com ênfase no envolvimento da comunidade de desenvolvedores o +mais cedo possível. + +:ref:`development_coding` é sobre o processo de codificação; muitas armadilhas +já encontradas por outros desenvolvedores são discutidas. Alguns requisitos +para patches são explicados, e é feita uma introdução para algumas ferramentas +que podem ajudar a garantir que os patches de kernel estão corretos. + +:ref:`development_posting` fala sobre o processo de envio de patches para +revisão. Para serem levados em consideração pela comunidade desenvolvedora, os +patches devem estar devidamente formatados e descritos, assim como devem estar +no lugar correto. Seguir os conselhos dessa seção pode ajudar na recepção +positiva do seu trabalho. + +:ref:`development_followthrough` cobre o que acontece após o envio dos patches; +o trabalho ainda está longe de estar concluído. Trabalhar com os revisores é +parte crucial do processo de desenvolvimento; essa seção oferece dicas de como +evitar problemas nesse estágio importante. Desenvolvedores são alertados a não +presumir que o trabalho acabou após o merge do patch no "mainline". + +:ref:`development_advancedtopics` introduz dois tópicos mais "avançados": +gerenciamento de patches com git e revisão de patches por outros. + +:ref:`development_conclusion` conclui o documento com indicações de fontes com +mais informações sobre o desenvolvimento do kernel. + +Sobre este documento +-------------------- + +O kernel Linux, com mais de 8 milhões de linhas de código e bem mais de 1000 +contribuintes a cada lançamento ("release"), é um dos maiores e mais ativos +projetos de software livre em existência. Desde seu modesto início em 1991, +este kernel evoluiu para se tornar um dos melhores componentes de sistemas +operacionais, rodando em pequenos players de música digital, PCs de mesa, os +maiores supercomputadores em existência, e todos os outros tipos de sistema +entre eles. É robusto, eficiente, e uma solução escalável para quase toda +situação. + +O crescimento do Linux trouxe o aumento no número de desenvolvedores (e +empresas) desejando participar no seu desenvolvimento. Fabricantes de hardware +querem garantir que o Linux suporte bem os seus produtos, tornando-os atrativos +para usuários Linux. Fabricantes de sistemas embarcados, que usam o Linux como +componente em um produto integrado, querem que o Linux seja tão capaz e +adequado quanto possível para a tarefa em questão. Distribuidores de software +que baseiam seus produtos em Linux têm claro interesse nas capacidades, +performance, e confiabilidade do kernel Linux. É também comum que usuários +finais queiram alterar o Linux para atender melhor suas necessidades. + +Uma das características mais atrativas do Linux é sua facilidade de acesso a +esses desenvolvedores; qualquer um com as habilidades necessárias pode melhorar +o Linux e influenciar a direção do seu desenvolvimento. Produtos proprietários +não conseguem oferecer esse tipo de abertura, que é característico do processo +de software livre. O kernel é ainda mais acessível que a maioria dos outros +projetos de software livre. Um ciclo típico de três meses de desenvolvimento +do kernel pode envolver mais de 1000 desenvolvedores trabalhando para mais de +100 empresas (ou absolutamente nenhuma empresa). + +Trabalhar com a comunidade de desenvolvimento do kernel não é uma tarefa árdua. +Contudo, muitos colaboradores potenciais passaram por dificuldades ao tentar +trabalhar no kernel. A comunidade evoluiu suas próprias formas de funcionamento +que permitem operar de forma fluida (e produzir um produto de alta qualidade) +em um ambiente em que milhares de linhas de código são alteradas todos os dias. +Não é surpresa que o processo de desenvolvimento do kernel Linux seja muito +diferente dos modelos de desenvolvimento proprietários. + +O processo de desenvolvimento do kernel pode parecer estranho e intimidador +para novos desenvolvedores, mas existem bons motivos e uma sólida experiência +por trás disso. Um desenvolvedor que não entenda os caminhos próprios da +comunidade kernel (ou pior, que tente menosprezá-los ou contorná-los) terá uma +experiência frustrante pela frente. A comunidade de desenvolvimento ajuda +aqueles que tentam aprender, mas gasta pouco tempo com aqueles que não escutam +ou não ligam para o processo de desenvolvimento. + +Espera-se que aqueles que leiam este documento sejam capazes de evitar essa +experiência frustrante. Há muito material aqui, mas o esforço envolvido na sua +leitura valerá a pena. A comunidade de desenvolvimento sempre necessita de +desenvolvedores que ajudem a melhorar o kernel; o texto a seguir deve ajudar +você - ou aqueles trabalhando para você - a se juntar à nossa comunidade. + +Créditos +-------- + +Esse documento foi escrito por Jonathan Corbet, corbet@lwn.net. Aprimorado +pelos comentários de 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, e Jochen Voß. + +Esse trabalho contou com o apoio da Linux Foundation; agradecimentos especiais +para Amanda McPherson, que viu o valor desse esforço e fez tudo acontecer. + +A importância de levar o código até o "mainline" +------------------------------------------------- + +Algumas empresas e desenvolvedores ocasionalmente se perguntam por que devem +se importar em aprender como trabalhar com a comunidade do kernel e ter seu +código no "mainline" (o kernel mantido por Linus Torvalds e usado como base +para os distribuidores Linux). No curto prazo, contribuir com o código pode +parecer um gasto evitável; parece mais fácil apenas manter o seu código à +parte e oferecer suporte direto aos usuários. A verdade é que manter código +fora da árvore principal ("out-of-tree") é uma falsa economia. + +Para ilustrar os custos do código "out-of-tree", aqui estão alguns aspectos +relevantes do processo de desenvolvimento do kernel; a maioria será discutida +com mais detalhes adiante neste documento. Considere: + +- Código integrado via merge ao "mainline" fica disponível para todos os + usuários Linux. Estará automaticamente presente em todas as distribuições + que o habilitarem. Não há necessidade de discos de armazenamento, downloads, + ou as complicações de dar suporte a múltiplas versões de variadas + distribuições; tudo simplesmente funciona, para o desenvolvedor e para o + usuário. Incorporação ao "mainline" resolve um grande número de problemas + de distribuição e suporte. + +- Enquanto desenvolvedores do kernel se esforçam para manter uma interface + estável para o espaço do usuário, a API interna está em constante mudança. + A ausência de uma interface interna estável é uma escolha deliberada de + design; permite que sejam feitas melhorias fundamentais a qualquer tempo e + resulta em código de qualidade superior. Uma consequência dessa política é + que código "out-of-tree" precisa ser constantemente atualizado para que + continue funcionando com novos kernels. Manter código "out-of-tree" requer + significativo trabalho apenas para mantê-lo funcionando. + + Por sua vez, código que está no "mainline" não precisa dessa manutenção, + resultado de uma regra simples que exige que qualquer desenvolvedor que + altere uma API, também conserte qualquer código que deixe de funcionar como + resultado da alteração. Código que teve o merge realizado no "mainline" tem + custo significativamente menor de manutenção. + +- Além disso, código que está no kernel será muitas vezes melhorado por outros + desenvolvedores. Resultados surpreendentes podem surgir ao permitir que sua + comunidade de usuários e clientes melhore seu produto. + +- Código do kernel está sujeito a revisão, tanto antes como depois do merge ao + "mainline". Independentemente das habilidades do desenvolvedor original, o + processo de revisão invariavelmente encontra maneiras de evoluí-lo. Bugs + severos e problemas de segurança são constantemente encontrados durante o + processo de revisão. Isso é especialmente válido para código desenvolvido em + ambiente isolado; tais códigos se beneficiam fortemente ao serem revistos por + outros desenvolvedores. Código "out-of-tree" é código de baixa qualidade. + +- Participação no processo de desenvolvimento é a forma pela qual você pode + influenciar a direção do desenvolvimento do kernel. Usuários que se queixam + externamente são ouvidos, porém desenvolvedores ativos têm maior poder de + articulação - e a habilidade de implementar mudanças que façam o kernel + funcionar melhor para suas necessidades. + +- Quando o código é mantido à parte, sempre existe a possibilidade de que + terceiros contribuam para uma implementação diferente de uma funcionalidade + parecida. Se isso acontecer, ter seu código integrado via merge se tornará + muito mais difícil - ao ponto de ser impossível. Você enfrentará duas + alternativas desagradáveis, (1) manter uma funcionalidade "out-of-tree" + indefinidamente ou (2) abandonar seu código e migrar seus usuários para a + versão na árvore principal ("in-tree"). + +- Contribuição de código é a ação fundamental que faz todo o processo + funcionar. Ao contribuir com seu código você pode adicionar nova + funcionalidade ao kernel e proporcionar capacidades e exemplos que podem ser + usados por outros desenvolvedores de kernel. Se você desenvolveu código para + o Linux (ou está pensando em desenvolver), você claramente tem interesse na + continuidade do sucesso dessa plataforma; contribuição de código é uma das + melhores maneiras de garantir esse sucesso. + +Todos os argumentos acima se aplicam a qualquer código "out-of-tree", incluindo +código distribuído de maneira proprietária, em formato exclusivamente binário. +Existem fatores adicionais que devem ser levados em consideração antes de +qualquer distribuição de código de kernel apenas em binário, incluindo: + +- As questões legais da distribuição de kernel proprietário são, no melhor dos + casos, confusas; muitos detentores de direitos autorais do kernel acreditam + que a maioria dos módulos binários são produtos derivados do kernel e que, + como resultado, sua distribuição é uma violação da Licença Pública Geral GNU + ("GNU General Public License"), que será tratada com mais profundidade abaixo. + Este autor não é um advogado, e nada neste documento pode ser considerado + aconselhamento jurídico. O verdadeiro status de módulos privados ("closed + source") só pode ser determinado judicialmente. Independentemente disso, a + incerteza que cerca esses módulos existe. + +- Os módulos binários aumentam consideravelmente a dificuldade de depuração de + problemas do kernel ("debugging"), a ponto de a maioria dos desenvolvedores + de kernel sequer tentar. Portanto, a distribuição de módulos exclusivamente + binários tornará mais difícil que os seus usuários recebam suporte. + +- O suporte também é mais difícil para distribuidores de módulos exclusivamente + binários, que precisam fornecer uma versão do módulo para cada distribuição e + cada versão do kernel que desejam suportar. Dezenas de versões de um único + módulo podem ser necessárias para fornecer uma cobertura razoavelmente + abrangente, e seus usuários terão que atualizar seu módulo separadamente + sempre que atualizarem seu kernel. + +- Tudo o que foi dito acima sobre revisão de código se aplica em dobro ao + código fechado. Como esse código não está disponível, ele não pode ter sido + revisado pela comunidade e, sem dúvida, terá sérios problemas. + +Os fabricantes de sistemas embarcados, em particular, podem ser tentados a +ignorar grande parte do que foi dito nesta seção, acreditando que estão +lançando um produto autossuficiente que usa uma versão congelada do kernel e +não requer mais desenvolvimento após o lançamento. Esse argumento ignora o +valor de uma revisão de código abrangente e o valor de permitir que seus +usuários adicionem recursos ao seu produto. Mas esses produtos também têm uma +vida comercial limitada, após a qual uma nova versão deve ser lançada. Nesse +ponto, os fornecedores cujo código está no "mainline" e bem mantido estarão em +uma posição muito melhor para preparar o novo produto para o mercado +rapidamente. + +Licenciamento +------------- + +Código é submetido ao kernel do Linux sob diversas licenças, mas todo ele deve +ser compatível com a versão 2 da Licença Pública Geral GNU (GPLv2), que é a +licença que cobre a distribuição do kernel como um todo. Na prática, isso +significa que todas as contribuições de código são cobertas pela GPLv2 (com, +opcionalmente, uma linguagem que permita a distribuição sob versões posteriores +da GPL) ou pela licença BSD de três cláusulas. Quaisquer contribuições que não +sejam cobertas por uma licença compatível não serão aceitas no kernel. + +A cessão de direitos autorais não é exigida (nem solicitada) para o código +contribuído para o kernel. Todo o código incorporado ao kernel principal mantém +sua titularidade original; como resultado, o kernel agora tem milhares de +proprietários. + +Uma implicação dessa estrutura de propriedade é que qualquer tentativa de +alterar o licenciamento do kernel está fadada ao fracasso quase certo. Existem +poucos cenários práticos em que o acordo de todos os detentores de direitos +autorais poderia ser obtido (ou seu código removido do kernel). Portanto, em +particular, não há perspectiva de migração para a versão 3 da GPL em um futuro +próximo. + +É imprescindível que todo o código contribuído para o kernel seja legitimamente +software livre. Por esse motivo, código de contribuidores sem identidade +conhecida ou contribuidores anônimos não será aceito. Todos os contribuidores +são obrigados a "assinar" seu código, declarando que ele pode ser distribuído +com o kernel sob a GPL. Código que não tenha sido licenciado como software +livre por seu proprietário, ou que apresente risco de criar problemas +relacionados a direitos autorais para o kernel (como código derivado de +esforços de engenharia reversa sem as devidas salvaguardas) não pode ser +contribuído. + +Questões sobre direitos autorais são comuns em listas de discussão de +desenvolvimento Linux. Normalmente, essas perguntas recebem muitas respostas, +mas é importante lembrar que as pessoas que respondem a essas perguntas não são +advogados e não podem fornecer aconselhamento jurídico. Se você tiver dúvidas +jurídicas relacionadas ao código-fonte do Linux, não há substituto para +conversar com um advogado especializado nessa área. Confiar em respostas +obtidas em listas de discussão técnicas é arriscado. From c423d3295a760da0f2943c5c14f9c3e8fae04390 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 17 Mar 2026 13:33:04 +0100 Subject: [PATCH 070/162] docs: reporting-issues: mention text is best viewed rendered Add a comment before the step-by-step guide explaining that the document is best viewed in the rendered form, as there the internal links will work that later patches will add. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/admin-guide/reporting-issues.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/admin-guide/reporting-issues.rst b/Documentation/admin-guide/reporting-issues.rst index a68e6d909274..049dd9b66351 100644 --- a/Documentation/admin-guide/reporting-issues.rst +++ b/Documentation/admin-guide/reporting-issues.rst @@ -48,6 +48,16 @@ Once the report is out, answer any questions that come up and help where you can. That includes keeping the ball rolling by occasionally retesting with newer releases and sending a status update afterwards. +.. + Note: If you see this note, you are reading the text's source file. You + might want to switch to a rendered version: It makes it a lot easier to + read and navigate this document -- especially when you want to look something + up in the reference section, then jump back to where you left off. +.. + Find the latest rendered version of this text here: + https://docs.kernel.org/admin-guide/reporting-issues.html + + Step-by-step guide how to report issues to the kernel maintainers ================================================================= From 83aa754da480ed665f99db5d6b73e7f1b9836976 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 17 Mar 2026 13:33:05 +0100 Subject: [PATCH 071/162] docs: reporting-issues: tweak the reference section intro Fine tuning to the intro of the reference section: * Call the step-by-step guide what it is. * Reorder the links to the guides on bug reporting to first mention the most modern one. * Many small changes to streamline the text and slightly shorten it. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: --- .../admin-guide/reporting-issues.rst | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/Documentation/admin-guide/reporting-issues.rst b/Documentation/admin-guide/reporting-issues.rst index 049dd9b66351..9f9c5db25a6c 100644 --- a/Documentation/admin-guide/reporting-issues.rst +++ b/Documentation/admin-guide/reporting-issues.rst @@ -244,42 +244,37 @@ The reference section below explains each of these steps in more detail. Reference section: Reporting issues to the kernel maintainers ============================================================= -The detailed guides above outline all the major steps in brief fashion, which -should be enough for most people. But sometimes there are situations where even -experienced users might wonder how to actually do one of those steps. That's -what this section is for, as it will provide a lot more details on each of the -above steps. Consider this as reference documentation: it's possible to read it -from top to bottom. But it's mainly meant to skim over and a place to look up -details how to actually perform those steps. +The step-by-step guide above outlines all the major steps in brief fashion, +which usually covers everything required. But even experienced users will +sometimes wonder how to actually realize some of those steps or why they are +needed; there are also corner cases the guide ignores for readability. That is +what the entries in this reference section are for, which provide additional +information for each of the steps in the guide. -A few words of general advice before digging into the details: +A few words of general advice: - * The Linux kernel developers are well aware this process is complicated and - demands more than other FLOSS projects. We'd love to make it simpler. But - that would require work in various places as well as some infrastructure, - which would need constant maintenance; nobody has stepped up to do that - work, so that's just how things are for now. +* The Linux developers are well aware that reporting bugs to them is more + complicated and demanding than in other FLOSS projects. Some of it is because + the kernel is different, among others due to its mail-driven development + process and because it consists mostly of drivers. Some of it is because + improving things would require work in several technical areas and people + triaging bugs –– and nobody has stepped up to do or fund that work. - * A warranty or support contract with some vendor doesn't entitle you to - request fixes from developers in the upstream Linux kernel community: such - contracts are completely outside the scope of the Linux kernel, its - development community, and this document. That's why you can't demand - anything such a contract guarantees in this context, not even if the - developer handling the issue works for the vendor in question. If you want - to claim your rights, use the vendor's support channel instead. When doing - so, you might want to mention you'd like to see the issue fixed in the - upstream Linux kernel; motivate them by saying it's the only way to ensure - the fix in the end will get incorporated in all Linux distributions. +* A warranty or support contract with some vendor doesn't entitle you to + request fixes from the upstream Linux developers: Such contracts are + completely outside the scope of the upstream Linux kernel, its development + community, and this document -- even if those handling the issue work for the + vendor who issued the contract. If you want to claim your rights, use the + vendor's support channel. - * If you never reported an issue to a FLOSS project before you should consider - reading `How to Report Bugs Effectively - `_, `How To Ask - Questions The Smart Way - `_, and `How to ask good - questions `_. +* If you never reported an issue to a FLOSS project before, consider skimming + guides like `How to ask good questions + `_, `How To Ask Questions The Smart Way + `_, and `How to Report + Bugs Effectively `_,. -With that off the table, find below the details on how to properly report -issues to the Linux kernel developers. +With that off the table, find below details for the steps from the detailed +guide on reporting issues to the Linux kernel developers. Make sure you're using the upstream Linux kernel From ceee0f73c3c6c45d4ffa4ebaf28a9094e0934779 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 17 Mar 2026 13:33:06 +0100 Subject: [PATCH 072/162] docs: reporting-issues: add conclusion to the step-by-step guide Text based on a section Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst and slightly improved after review feedback. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/admin-guide/reporting-issues.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/admin-guide/reporting-issues.rst b/Documentation/admin-guide/reporting-issues.rst index 9f9c5db25a6c..aa058b295c5f 100644 --- a/Documentation/admin-guide/reporting-issues.rst +++ b/Documentation/admin-guide/reporting-issues.rst @@ -241,6 +241,20 @@ kernels regularly rebased on those. If that is the case, follow these steps: The reference section below explains each of these steps in more detail. +Conclusion of the step-by-step guide +------------------------------------ + +Did you run into trouble following the step-by-step guide not cleared up by the +reference section below? Did you spot errors? Or do you have ideas on how to +improve the guide? + +If any of that applies, please let the developers know by sending a short note +or a patch to Thorsten Leemhuis while ideally CCing the +public Linux docs mailing list . Such feedback is +vital to improve this text further, which is in everybody's interest, as it will +enable more people to master the task described here. + + Reference section: Reporting issues to the kernel maintainers ============================================================= From a9a1c262df0bbe43ea7a69fe0a97dc68fcc6ba66 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 17 Mar 2026 13:33:07 +0100 Subject: [PATCH 073/162] =?UTF-8?q?docs:=20verify-bugs-=E2=80=A6=20and=20q?= =?UTF-8?q?uickly-build-=E2=80=A6:=20improve=20feedback=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mention sending patches in the section about feedback. This syncs them with a section a earlier patch added to reporting-issues.rst, which was based on these sections and improved during review. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: --- .../admin-guide/quickly-build-trimmed-linux.rst | 14 ++++++++------ .../verify-bugs-and-bisect-regressions.rst | 15 +++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Documentation/admin-guide/quickly-build-trimmed-linux.rst b/Documentation/admin-guide/quickly-build-trimmed-linux.rst index cb4b78468a93..cb178e0a6208 100644 --- a/Documentation/admin-guide/quickly-build-trimmed-linux.rst +++ b/Documentation/admin-guide/quickly-build-trimmed-linux.rst @@ -349,12 +349,14 @@ again. .. _submit_improvements_qbtl: -Did you run into trouble following any of the above steps that is not cleared up -by the reference section below? Or do you have ideas how to improve the text? -Then please take a moment of your time and let the maintainer of this document -know by email (Thorsten Leemhuis ), ideally while CCing the -Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is vital to -improve this document further, which is in everybody's interest, as it will +Did you run into trouble following the step-by-step guide not cleared up by the +reference section below? Did you spot errors? Or do you have ideas on how to +improve the guide? + +If any of that applies, please let the developers know by sending a short note +or a patch to Thorsten Leemhuis while ideally CCing the +public Linux docs mailing list . Such feedback is +vital to improve this text further, which is in everybody's interest, as it will enable more people to master the task described here. Reference section for the step-by-step guide diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index d83601f2a459..7d38393f31fb 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -1062,16 +1062,15 @@ Conclusion You have reached the end of the step-by-step guide. -Did you run into trouble following any of the above steps not cleared up by the -reference section below? Did you spot errors? Or do you have ideas how to +Did you run into trouble following the step-by-step guide not cleared up by the +reference section below? Did you spot errors? Or do you have ideas on how to improve the guide? -If any of that applies, please take a moment and let the maintainer of this -document know by email (Thorsten Leemhuis ), ideally while -CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is -vital to improve this text further, which is in everybody's interest, as it -will enable more people to master the task described here -- and hopefully also -improve similar guides inspired by this one. +If any of that applies, please let the developers know by sending a short note +or a patch to Thorsten Leemhuis while ideally CCing the +public Linux docs mailing list . Such feedback is +vital to improve this text further, which is in everybody's interest, as it will +enable more people to master the task described here. Reference section for the step-by-step guide From 9d437400745edec29eba221c41380a5ae0d925f5 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 17 Mar 2026 13:33:08 +0100 Subject: [PATCH 074/162] docs: reporting-issues: create a proper appendix explaining specialties Merge "Why some bugs remain unfixed and some reports are ignored" with the closing words while rewriting and extending the text. The result spends fewer words on explaining things that are normal in FLOSS -- while outlining where the kernel is different and how that makes bug reporting more complicated than in other FLOSS projects. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Message-ID: <473b36fa9723c46b7167004752f097e6c26d7278.1773750701.git.linux@leemhuis.info> --- .../admin-guide/reporting-issues.rst | 101 ++++++++---------- 1 file changed, 44 insertions(+), 57 deletions(-) diff --git a/Documentation/admin-guide/reporting-issues.rst b/Documentation/admin-guide/reporting-issues.rst index aa058b295c5f..16a66a1f1975 100644 --- a/Documentation/admin-guide/reporting-issues.rst +++ b/Documentation/admin-guide/reporting-issues.rst @@ -1693,72 +1693,59 @@ for the subsystem where the issue seems to have its roots; CC the mailing list for the subsystem as well as the stable mailing list (stable@vger.kernel.org). -Why some issues won't get any reaction or remain unfixed after being reported -============================================================================= +Appendix: Why it is somewhat hard to report kernel bugs +======================================================= -When reporting a problem to the Linux developers, be aware only 'issues of high -priority' (regressions, security issues, severe problems) are definitely going -to get resolved. The maintainers or if all else fails Linus Torvalds himself -will make sure of that. They and the other kernel developers will fix a lot of -other issues as well. But be aware that sometimes they can't or won't help; and -sometimes there isn't even anyone to send a report to. +The Linux kernel developers are well aware that reporting bugs to them is harder +than in other Free/Libre Open Source Projects. Many reasons for that lie in the +nature of kernels, Linux' development model, and how the world uses the kernel: -This is best explained with kernel developers that contribute to the Linux -kernel in their spare time. Quite a few of the drivers in the kernel were -written by such programmers, often because they simply wanted to make their -hardware usable on their favorite operating system. +* *Most kernels of Linux distributions are totally unsuitable for reporting bugs + upstream.* The reference section above already explained this in detail: + outdated codebases as well as modifications and add-ons lead to kernel bugs + that were fixed upstream a long time ago or never happened there in the first + place. Developers of other Open Source software face these problems as well, + but the situation is a lot worse when it comes to the kernel, as the changes + and their impact are much more severe -- which is why many kernel developers + expect reports with kernels built from fresh and nearly unmodified sources. -These programmers most of the time will happily fix problems other people -report. But nobody can force them to do, as they are contributing voluntarily. +* *Bugs often only occur in a special environment.* That is because Linux is + mostly drivers and can be used in a multitude of ways. Developers often do not + have a matching setup at hand -- and therefore frequently must rely on bug + reporters for isolating a problems's cause and testing proposed fixes. -Then there are situations where such developers really want to fix an issue, -but can't: sometimes they lack hardware programming documentation to do so. -This often happens when the publicly available docs are superficial or the -driver was written with the help of reverse engineering. +* *The kernel has hundreds of maintainers, but all-rounders are very rare.* That + again is and effect caused by the multitude of features and drivers, due to + which many kernel developers know little about lower or higher layers related + to their code and even less about other areas. -Sooner or later spare time developers will also stop caring for the driver. -Maybe their test hardware broke, got replaced by something more fancy, or is so -old that it's something you don't find much outside of computer museums -anymore. Sometimes developer stops caring for their code and Linux at all, as -something different in their life became way more important. In some cases -nobody is willing to take over the job as maintainer – and nobody can be forced -to, as contributing to the Linux kernel is done on a voluntary basis. Abandoned -drivers nevertheless remain in the kernel: they are still useful for people and -removing would be a regression. +* *It is hard finding where to report issues to, among others, due to the lack + of a central bug tracker.* This is something even some kernel developers + dislike, but that's the situation everyone has to deal with currently. -The situation is not that different with developers that are paid for their -work on the Linux kernel. Those contribute most changes these days. But their -employers sooner or later also stop caring for their code or make its -programmer focus on other things. Hardware vendors for example earn their money -mainly by selling new hardware; quite a few of them hence are not investing -much time and energy in maintaining a Linux kernel driver for something they -stopped selling years ago. Enterprise Linux distributors often care for a -longer time period, but in new versions often leave support for old and rare -hardware aside to limit the scope. Often spare time contributors take over once -a company orphans some code, but as mentioned above: sooner or later they will -leave the code behind, too. +* *Stable and longterm kernels are primarily maintained by a dedicated 'stable + team', which only handles regressions introduced within stable and longterm + series.* When someone reports a bug, say, using Linux 6.1.2, the team will, + therefore, always ask if mainline is affected: if the bug already happened + in 6.1 or occurs with latest mainline (say, 6.2-rc3), they in everybody's + interest shove it to the regular developers, as those know the code best. -Priorities are another reason why some issues are not fixed, as maintainers -quite often are forced to set those, as time to work on Linux is limited. -That's true for spare time or the time employers grant their developers to -spend on maintenance work on the upstream kernel. Sometimes maintainers also -get overwhelmed with reports, even if a driver is working nearly perfectly. To -not get completely stuck, the programmer thus might have no other choice than -to prioritize issue reports and reject some of them. +* *Linux developers are free to focus on latest mainline.* Some, thus, react + coldly to reports about bugs in, say, Linux 6.0 when 6.1 is already out; + even the latter might not be enough once 6.2-rc1 is out. Some will also not + be very welcoming to reports with 6.1.5 or 6.1.6, as the problem might be a + series-specific regression the stable team (see above) caused and must fix. -But don't worry too much about all of this, a lot of drivers have active -maintainers who are quite interested in fixing as many issues as possible. - - -Closing words -============= - -Compared with other Free/Libre & Open Source Software it's hard to report -issues to the Linux kernel developers: the length and complexity of this -document and the implications between the lines illustrate that. But that's how -it is for now. The main author of this text hopes documenting the state of the -art will lay some groundwork to improve the situation over time. +* *Sometimes there is nobody to help.* Sometimes this is due to the lack of + hardware documentation -- for example, when a driver was built using reverse + engineering or was taken over by spare-time developers when the hardware + manufacturer left it behind. Other times there is nobody to even report bugs + to: when maintainers move on without a replacement, their code often remains + in the kernel as long as it's useful. +Some of these aspects could be improved to facilitate bug reporting -- many +Linux kernel developers are well aware of this and would be glad if a few +individuals or an entity would make this their mission. .. end-of-content From 117376394061780680dd4bfd92ea30bf9deafedf Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 10 Mar 2026 13:14:31 +0100 Subject: [PATCH 075/162] coccinelle: update Coccinelle URL The LIP6 URL no longer functions. Signed-off-by: Julia Lawall Signed-off-by: Jonathan Corbet Message-ID: <20260310121431.362091-1-Julia.Lawall@inria.fr> --- Documentation/dev-tools/coccinelle.rst | 2 +- Documentation/translations/it_IT/process/4.Coding.rst | 3 ++- Documentation/translations/sp_SP/process/4.Coding.rst | 3 ++- Documentation/translations/zh_CN/process/4.Coding.rst | 2 +- Documentation/translations/zh_TW/process/4.Coding.rst | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst index f73ccf5397f3..b8ecb481ddff 100644 --- a/Documentation/dev-tools/coccinelle.rst +++ b/Documentation/dev-tools/coccinelle.rst @@ -35,7 +35,7 @@ of many distributions, e.g. : Some distribution packages are obsolete and it is recommended to use the latest version released from the Coccinelle homepage at -http://coccinelle.lip6.fr/ +https://coccinelle.gitlabpages.inria.fr/website Or from Github at: diff --git a/Documentation/translations/it_IT/process/4.Coding.rst b/Documentation/translations/it_IT/process/4.Coding.rst index 3126342c4b4a..a2ec35e016b7 100644 --- a/Documentation/translations/it_IT/process/4.Coding.rst +++ b/Documentation/translations/it_IT/process/4.Coding.rst @@ -329,7 +329,8 @@ Sparse deve essere installato separatamente (se il vostra distribuzione non lo prevede, potete trovarlo su https://sparse.wiki.kernel.org/index.php/Main_Page); può essere attivato sul codice aggiungendo "C=1" al comando make. -Lo strumento "Coccinelle" (http://coccinelle.lip6.fr/) è in grado di trovare +Lo strumento "Coccinelle" (https://coccinelle.gitlabpages.inria.fr/website/) +è in grado di trovare una vasta varietà di potenziali problemi di codifica; e può inoltre proporre soluzioni per risolverli. Un buon numero di "patch semantiche" per il kernel sono state preparate nella cartella scripts/coccinelle; utilizzando diff --git a/Documentation/translations/sp_SP/process/4.Coding.rst b/Documentation/translations/sp_SP/process/4.Coding.rst index 7cc347c34354..6c3750ccdea2 100644 --- a/Documentation/translations/sp_SP/process/4.Coding.rst +++ b/Documentation/translations/sp_SP/process/4.Coding.rst @@ -336,7 +336,8 @@ https://sparse.wiki.kernel.org/index.php/Main_Page si su distribución no lo empaqueta); luego, puede ejecutarse en el código agregando "C=1" a su comando make. -La herramienta "Coccinelle" (http://coccinelle.lip6.fr/) puede encontrar +La herramienta "Coccinelle" (https://coccinelle.gitlabpages.inria.fr/website/) +puede encontrar una amplia variedad de posibles problemas de codificación; también puede proponer correcciones para esos problemas. Bastantes "parches semánticos" para el kernel se han empaquetado en el directorio scripts/coccinelle; diff --git a/Documentation/translations/zh_CN/process/4.Coding.rst b/Documentation/translations/zh_CN/process/4.Coding.rst index 4cc35d410dbc..a00ad5d6b81e 100644 --- a/Documentation/translations/zh_CN/process/4.Coding.rst +++ b/Documentation/translations/zh_CN/process/4.Coding.rst @@ -216,7 +216,7 @@ Documentation/fault-injection/fault-injection.rst。 可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到), 然后可以通过在make命令中添加“C=1”在代码上运行它。 -“Coccinelle”工具 :ref:`http://coccinelle.lip6.fr/ ` +“Coccinelle”工具 :ref:`https://coccinelle.gitlabpages.inria.fr/website/ ` 能够发现各种潜在的编码问题;它还可以为这些问题提出修复方案。在 scripts/coccinelle目录下已经打包了相当多的内核“语义补丁”;运行 “make coccicheck”将运行这些语义补丁并报告发现的任何问题。有关详细信息,请参阅 diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst index e90a6b51fb98..233e8718ed41 100644 --- a/Documentation/translations/zh_TW/process/4.Coding.rst +++ b/Documentation/translations/zh_TW/process/4.Coding.rst @@ -219,7 +219,7 @@ Documentation/fault-injection/fault-injection.rst。 可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到), 然後可以通過在make命令中添加“C=1”在代碼上運行它。 -“Coccinelle”工具 :ref:`http://coccinelle.lip6.fr/ ` +“Coccinelle”工具 :ref:`https://coccinelle.gitlabpages.inria.fr/website/ ` 能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修復方案。在 scripts/coccinelle目錄下已經打包了相當多的內核“語義補丁”;運行 “make coccicheck”將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱 From cae0e1bbde87750ea6976e4ecbaa424de859d7ba Mon Sep 17 00:00:00 2001 From: Daniel Tang Date: Mon, 9 Mar 2026 21:05:21 -0400 Subject: [PATCH 076/162] docs: path-lookup: fix unrenamed WALK_GET The symbol WALK_GET does not appears in the codebase as of 0031c06807cfa8aa. It was renamed as of 8f64fb1ccef33107. A previous documentation update, de9414adafe4, renamed one occurrence in path-lookup.rst, but forgot to change another occurrence later in the file. Fixes: de9414adafe4 ("docs: path-lookup: update WALK_GET, WALK_PUT desc") Signed-off-by: Daniel Tang Signed-off-by: Jonathan Corbet Message-ID: <13011949.O9o76ZdvQC@daniel-desktop3> --- Documentation/filesystems/path-lookup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/path-lookup.rst b/Documentation/filesystems/path-lookup.rst index 9ced1135608e..6957c70f18db 100644 --- a/Documentation/filesystems/path-lookup.rst +++ b/Documentation/filesystems/path-lookup.rst @@ -1364,7 +1364,7 @@ it sets ``LOOKUP_AUTOMOUNT``, as does "``quotactl()``" and the handling of symlinks. Some system calls set or clear it implicitly, while others have API flags such as ``AT_SYMLINK_FOLLOW`` and ``UMOUNT_NOFOLLOW`` to control it. Its effect is similar to -``WALK_GET`` that we already met, but it is used in a different way. +``WALK_TRAILING`` that we already met, but it is used in a different way. ``LOOKUP_DIRECTORY`` insists that the final component is a directory. Various callers set this and it is also set when the final component From 6108c809f4fd9dbb1a138ba4326d645cc3113a8d Mon Sep 17 00:00:00 2001 From: Haoyang LIU Date: Mon, 9 Mar 2026 15:47:15 +0800 Subject: [PATCH 077/162] tools/docs/checktransupdate.py: fix all issues reported by pylint This patch fixes all issues reported by pylint, including: 1. Format issue in logging. 2. Variable name style issue. Fixes: 63e96ce050e5 ("scripts: fix all issues reported by pylint") Signed-off-by: Haoyang LIU Signed-off-by: Jonathan Corbet Message-ID: <20260309074716.10739-1-tttturtleruss@gmail.com> --- tools/docs/checktransupdate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docs/checktransupdate.py b/tools/docs/checktransupdate.py index f296a969f02c..d7b98753e35f 100755 --- a/tools/docs/checktransupdate.py +++ b/tools/docs/checktransupdate.py @@ -78,11 +78,11 @@ def get_origin_from_trans_smartly(origin_path, t_from_head): (2) Update the translation through commit HASH (TITLE) """ # catch flag for 12-bit commit hash - HASH = r'([0-9a-f]{12})' + hash_re = r'([0-9a-f]{12})' # pattern 1: contains "update to commit HASH" - pat_update_to = re.compile(rf'update to commit {HASH}') + pat_update_to = re.compile(rf'update to commit {hash_re}') # pattern 2: contains "Update the translation through commit HASH" - pat_update_translation = re.compile(rf'Update the translation through commit {HASH}') + pat_update_translation = re.compile(rf'Update the translation through commit {hash_re}') origin_commit_hash = None for line in t_from_head["message"]: @@ -133,7 +133,7 @@ def check_per_file(file_path): opath = get_origin_path(file_path) if not os.path.isfile(opath): - logging.error("Cannot find the origin path for {file_path}") + logging.error("Cannot find the origin path for %s", file_path) return o_from_head = get_latest_commit_from(opath, "HEAD") From 023aabb6ccb298add344cab7c00c5f27b10319aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:21 +0100 Subject: [PATCH 078/162] docs: python: add helpers to run unit tests While python internal libraries have support for unit tests, its output is not nice. Add a helper module to improve its output. I wrote this module last year while testing some scripts I used internally. The initial skeleton was generated with the help of LLM tools, but it was higly modified to ensure that it will work as I would expect. Signed-off-by: Mauro Carvalho Chehab Message-ID: <37999041f616ddef41e84cf2686c0264d1a51dc9.1773074166.git.mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/tools/python.rst | 2 + Documentation/tools/unittest.rst | 24 ++ tools/lib/python/unittest_helper.py | 353 ++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 Documentation/tools/unittest.rst create mode 100755 tools/lib/python/unittest_helper.py diff --git a/Documentation/tools/python.rst b/Documentation/tools/python.rst index 1444c1816735..3b7299161f20 100644 --- a/Documentation/tools/python.rst +++ b/Documentation/tools/python.rst @@ -11,3 +11,5 @@ Python libraries feat kdoc kabi + + unittest diff --git a/Documentation/tools/unittest.rst b/Documentation/tools/unittest.rst new file mode 100644 index 000000000000..14a2b2a65236 --- /dev/null +++ b/Documentation/tools/unittest.rst @@ -0,0 +1,24 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Python unittest +=============== + +Checking consistency of python modules can be complex. Sometimes, it is +useful to define a set of unit tests to help checking them. + +While the actual test implementation is usecase dependent, Python already +provides a standard way to add unit tests by using ``import unittest``. + +Using such class, requires setting up a test suite. Also, the default format +is a little bit ackward. To improve it and provide a more uniform way to +report errors, some unittest classes and functions are defined. + + +Unittest helper module +====================== + +.. automodule:: lib.python.unittest_helper + :members: + :show-inheritance: + :undoc-members: diff --git a/tools/lib/python/unittest_helper.py b/tools/lib/python/unittest_helper.py new file mode 100755 index 000000000000..55d444cd73d4 --- /dev/null +++ b/tools/lib/python/unittest_helper.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2025-2026: Mauro Carvalho Chehab . +# +# pylint: disable=C0103,R0912,R0914,E1101 + +""" +Provides helper functions and classes execute python unit tests. + +Those help functions provide a nice colored output summary of each +executed test and, when a test fails, it shows the different in diff +format when running in verbose mode, like:: + + $ tools/unittests/nested_match.py -v + ... + Traceback (most recent call last): + File "/new_devel/docs/tools/unittests/nested_match.py", line 69, in test_count_limit + self.assertEqual(replaced, "bar(a); bar(b); foo(c)") + ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + AssertionError: 'bar(a) foo(b); foo(c)' != 'bar(a); bar(b); foo(c)' + - bar(a) foo(b); foo(c) + ? ^^^^ + + bar(a); bar(b); foo(c) + ? ^^^^^ + ... + +It also allows filtering what tests will be executed via ``-k`` parameter. + +Typical usage is to do:: + + from unittest_helper import run_unittest + ... + + if __name__ == "__main__": + run_unittest(__file__) + +If passing arguments is needed, on a more complex scenario, it can be +used like on this example:: + + from unittest_helper import TestUnits, run_unittest + ... + env = {'sudo': ""} + ... + if __name__ == "__main__": + runner = TestUnits() + base_parser = runner.parse_args() + base_parser.add_argument('--sudo', action='store_true', + help='Enable tests requiring sudo privileges') + + args = base_parser.parse_args() + + # Update module-level flag + if args.sudo: + env['sudo'] = "1" + + # Run tests with customized arguments + runner.run(__file__, parser=base_parser, args=args, env=env) +""" + +import argparse +import atexit +import os +import re +import unittest +import sys + +from unittest.mock import patch + + +class Summary(unittest.TestResult): + """ + Overrides ``unittest.TestResult`` class to provide a nice colored + summary. When in verbose mode, displays actual/expected difference in + unified diff format. + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + #: Dictionary to store organized test results. + self.test_results = {} + + #: max length of the test names. + self.max_name_length = 0 + + def startTest(self, test): + super().startTest(test) + test_id = test.id() + parts = test_id.split(".") + + # Extract module, class, and method names + if len(parts) >= 3: + module_name = parts[-3] + else: + module_name = "" + if len(parts) >= 2: + class_name = parts[-2] + else: + class_name = "" + + method_name = parts[-1] + + # Build the hierarchical structure + if module_name not in self.test_results: + self.test_results[module_name] = {} + + if class_name not in self.test_results[module_name]: + self.test_results[module_name][class_name] = [] + + # Track maximum test name length for alignment + display_name = f"{method_name}:" + + self.max_name_length = max(len(display_name), self.max_name_length) + + def _record_test(self, test, status): + test_id = test.id() + parts = test_id.split(".") + if len(parts) >= 3: + module_name = parts[-3] + else: + module_name = "" + if len(parts) >= 2: + class_name = parts[-2] + else: + class_name = "" + method_name = parts[-1] + self.test_results[module_name][class_name].append((method_name, status)) + + def addSuccess(self, test): + super().addSuccess(test) + self._record_test(test, "OK") + + def addFailure(self, test, err): + super().addFailure(test, err) + self._record_test(test, "FAIL") + + def addError(self, test, err): + super().addError(test, err) + self._record_test(test, "ERROR") + + def addSkip(self, test, reason): + super().addSkip(test, reason) + self._record_test(test, f"SKIP ({reason})") + + def printResults(self): + """ + Print results using colors if tty. + """ + # Check for ANSI color support + use_color = sys.stdout.isatty() + COLORS = { + "OK": "\033[32m", # Green + "FAIL": "\033[31m", # Red + "SKIP": "\033[1;33m", # Yellow + "PARTIAL": "\033[33m", # Orange + "EXPECTED_FAIL": "\033[36m", # Cyan + "reset": "\033[0m", # Reset to default terminal color + } + if not use_color: + for c in COLORS: + COLORS[c] = "" + + # Calculate maximum test name length + if not self.test_results: + return + try: + lengths = [] + for module in self.test_results.values(): + for tests in module.values(): + for test_name, _ in tests: + lengths.append(len(test_name) + 1) # +1 for colon + max_length = max(lengths) + 2 # Additional padding + except ValueError: + sys.exit("Test list is empty") + + # Print results + for module_name, classes in self.test_results.items(): + print(f"{module_name}:") + for class_name, tests in classes.items(): + print(f" {class_name}:") + for test_name, status in tests: + # Get base status without reason for SKIP + if status.startswith("SKIP"): + status_code = status.split()[0] + else: + status_code = status + color = COLORS.get(status_code, "") + print( + f" {test_name + ':':<{max_length}}{color}{status}{COLORS['reset']}" + ) + print() + + # Print summary + print(f"\nRan {self.testsRun} tests", end="") + if hasattr(self, "timeTaken"): + print(f" in {self.timeTaken:.3f}s", end="") + print() + + if not self.wasSuccessful(): + print(f"\n{COLORS['FAIL']}FAILED (", end="") + failures = getattr(self, "failures", []) + errors = getattr(self, "errors", []) + if failures: + print(f"failures={len(failures)}", end="") + if errors: + if failures: + print(", ", end="") + print(f"errors={len(errors)}", end="") + print(f"){COLORS['reset']}") + + +def flatten_suite(suite): + """Flatten test suite hierarchy.""" + tests = [] + for item in suite: + if isinstance(item, unittest.TestSuite): + tests.extend(flatten_suite(item)) + else: + tests.append(item) + return tests + + +class TestUnits: + """ + Helper class to set verbosity level. + + This class discover test files, import its unittest classes and + executes the test on it. + """ + def parse_args(self): + """Returns a parser for command line arguments.""" + parser = argparse.ArgumentParser(description="Test runner with regex filtering") + parser.add_argument("-v", "--verbose", action="count", default=1) + parser.add_argument("-f", "--failfast", action="store_true") + parser.add_argument("-k", "--keyword", + help="Regex pattern to filter test methods") + return parser + + def run(self, caller_file=None, pattern=None, + suite=None, parser=None, args=None, env=None): + """ + Execute all tests from the unity test file. + + It contains several optional parameters: + + ``caller_file``: + - name of the file that contains test. + + typical usage is to place __file__ at the caller test, e.g.:: + + if __name__ == "__main__": + TestUnits().run(__file__) + + ``pattern``: + - optional pattern to match multiple file names. Defaults + to basename of ``caller_file``. + + ``suite``: + - an unittest suite initialized by the caller using + ``unittest.TestLoader().discover()``. + + ``parser``: + - an argparse parser. If not defined, this helper will create + one. + + ``args``: + - an ``argparse.Namespace`` data filled by the caller. + + ``env``: + - environment variables that will be passed to the test suite + + At least ``caller_file`` or ``suite`` must be used, otherwise a + ``TypeError`` will be raised. + """ + if not args: + if not parser: + parser = self.parse_args() + args = parser.parse_args() + + if not caller_file and not suite: + raise TypeError("Either caller_file or suite is needed at TestUnits") + + verbose = args.verbose + + if not env: + env = os.environ.copy() + + env["VERBOSE"] = f"{verbose}" + + patcher = patch.dict(os.environ, env) + patcher.start() + # ensure it gets stopped after + atexit.register(patcher.stop) + + + if verbose >= 2: + unittest.TextTestRunner(verbosity=verbose).run = lambda suite: suite + + # Load ONLY tests from the calling file + if not suite: + if not pattern: + pattern = caller_file + + loader = unittest.TestLoader() + suite = loader.discover(start_dir=os.path.dirname(caller_file), + pattern=os.path.basename(caller_file)) + + # Flatten the suite for environment injection + tests_to_inject = flatten_suite(suite) + + # Filter tests by method name if -k specified + if args.keyword: + try: + pattern = re.compile(args.keyword) + filtered_suite = unittest.TestSuite() + for test in tests_to_inject: # Use the pre-flattened list + method_name = test.id().split(".")[-1] + if pattern.search(method_name): + filtered_suite.addTest(test) + suite = filtered_suite + except re.error as e: + sys.stderr.write(f"Invalid regex pattern: {e}\n") + sys.exit(1) + else: + # Maintain original suite structure if no keyword filtering + suite = unittest.TestSuite(tests_to_inject) + + if verbose >= 2: + resultclass = None + else: + resultclass = Summary + + runner = unittest.TextTestRunner(verbosity=args.verbose, + resultclass=resultclass, + failfast=args.failfast) + result = runner.run(suite) + if resultclass: + result.printResults() + + sys.exit(not result.wasSuccessful()) + + +def run_unittest(fname): + """ + Basic usage of TestUnits class. + + Use it when there's no need to pass any extra argument to the tests + with. The recommended way is to place this at the end of each + unittest module:: + + if __name__ == "__main__": + run_unittest(__file__) + """ + TestUnits().run(fname) From c6c23449b3029757864c6895420296acbe096534 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:22 +0100 Subject: [PATCH 079/162] unittests: add a testbench to check public/private kdoc comments Add unit tests to check if the public/private and comments strip is working properly. Running it shows that, on several cases, public/private is not doing what it is expected: test_private: TestPublicPrivate: test balanced_inner_private: OK test balanced_non_greddy_private: OK test balanced_private: OK test no private: OK test unbalanced_inner_private: FAIL test unbalanced_private: FAIL test unbalanced_struct_group_tagged_with_private: FAIL test unbalanced_two_struct_group_tagged_first_with_private: FAIL test unbalanced_without_end_of_line: FAIL Ran 9 tests FAILED (failures=5) Signed-off-by: Mauro Carvalho Chehab Message-ID: <144f4952e0cb74fe9c9adc117e9a21ec8aa1cc10.1773074166.git.mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet Message-ID: --- tools/unittests/test_private.py | 331 ++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100755 tools/unittests/test_private.py diff --git a/tools/unittests/test_private.py b/tools/unittests/test_private.py new file mode 100755 index 000000000000..eae245ae8a12 --- /dev/null +++ b/tools/unittests/test_private.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python3 + +""" +Unit tests for struct/union member extractor class. +""" + + +import os +import re +import unittest +import sys + +from unittest.mock import MagicMock + +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) + +from kdoc.kdoc_parser import trim_private_members +from unittest_helper import run_unittest + +# +# List of tests. +# +# The code will dynamically generate one test for each key on this dictionary. +# + +#: Tests to check if CTokenizer is handling properly public/private comments. +TESTS_PRIVATE = { + # + # Simplest case: no private. Ensure that trimming won't affect struct + # + "no private": { + "source": """ + struct foo { + int a; + int b; + int c; + }; + """, + "trimmed": """ + struct foo { + int a; + int b; + int c; + }; + """, + }, + + # + # Play "by the books" by always having a public in place + # + + "balanced_private": { + "source": """ + struct foo { + int a; + /* private: */ + int b; + /* public: */ + int c; + }; + """, + "trimmed": """ + struct foo { + int a; + int c; + }; + """, + }, + + "balanced_non_greddy_private": { + "source": """ + struct foo { + int a; + /* private: */ + int b; + /* public: */ + int c; + /* private: */ + int d; + /* public: */ + int e; + + }; + """, + "trimmed": """ + struct foo { + int a; + int c; + int e; + }; + """, + }, + + "balanced_inner_private": { + "source": """ + struct foo { + struct { + int a; + /* private: ignore below */ + int b; + /* public: but this should not be ignored */ + }; + int b; + }; + """, + "trimmed": """ + struct foo { + struct { + int a; + }; + int b; + }; + """, + }, + + # + # Test what happens if there's no public after private place + # + + "unbalanced_private": { + "source": """ + struct foo { + int a; + /* private: */ + int b; + int c; + }; + """, + "trimmed": """ + struct foo { + int a; + }; + """, + }, + + "unbalanced_inner_private": { + "source": """ + struct foo { + struct { + int a; + /* private: ignore below */ + int b; + /* but this should not be ignored */ + }; + int b; + }; + """, + "trimmed": """ + struct foo { + struct { + int a; + }; + int b; + }; + """, + }, + + "unbalanced_struct_group_tagged_with_private": { + "source": """ + struct page_pool_params { + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + }; + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + /* private: used by test code only */ + void (*init_callback)(netmem_ref netmem, void *arg); + void *init_arg; + }; + }; + """, + "trimmed": """ + struct page_pool_params { + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + }; + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + }; + }; + """, + }, + + "unbalanced_two_struct_group_tagged_first_with_private": { + "source": """ + struct page_pool_params { + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + /* private: used by test code only */ + void (*init_callback)(netmem_ref netmem, void *arg); + void *init_arg; + }; + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + }; + }; + """, + "trimmed": """ + struct page_pool_params { + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + }; + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + }; + }; + """, + }, + "unbalanced_without_end_of_line": { + "source": """ \ + struct page_pool_params { \ + struct_group_tagged(page_pool_params_slow, slow, \ + struct net_device *netdev; \ + unsigned int queue_idx; \ + unsigned int flags; + /* private: used by test code only */ + void (*init_callback)(netmem_ref netmem, void *arg); \ + void *init_arg; \ + }; \ + struct_group_tagged(page_pool_params_fast, fast, \ + unsigned int order; \ + unsigned int pool_size; \ + int nid; \ + struct device *dev; \ + struct napi_struct *napi; \ + enum dma_data_direction dma_dir; \ + unsigned int max_len; \ + unsigned int offset; \ + }; \ + }; + """, + "trimmed": """ + struct page_pool_params { + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + }; + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + }; + }; + """, + }, +} + + +class TestPublicPrivate(unittest.TestCase): + """ + Main test class. Populated dynamically at runtime. + """ + + def setUp(self): + self.maxDiff = None + + def add_test(cls, name, source, trimmed): + """ + Dynamically add a test to the class + """ + def test(cls): + result = trim_private_members(source) + + result = re.sub(r"\s++", " ", result).strip() + expected = re.sub(r"\s++", " ", trimmed).strip() + + msg = f"failed when parsing this source:\n" + source + + cls.assertEqual(result, expected, msg=msg) + + test.__name__ = f'test {name}' + + setattr(TestPublicPrivate, test.__name__, test) + + +# +# Populate TestPublicPrivate class +# +test_class = TestPublicPrivate() +for name, test in TESTS_PRIVATE.items(): + test_class.add_test(name, test["source"], test["trimmed"]) + + +# +# main +# +if __name__ == "__main__": + run_unittest(__file__) From b1e64e30fce86e61d3b09f9352b262622f3f0cda Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:23 +0100 Subject: [PATCH 080/162] docs: kdoc: don't add broken comments inside prototypes Parsing a file like drivers/scsi/isci/host.h, which contains broken kernel-doc markups makes it create a prototype that contains unmatched end comments. That causes, for instance, struct sci_power_control to be shown this this prototype: struct sci_power_control { * it is not. */ bool timer_started; */ struct sci_timer timer; * requesters field. */ u8 phys_waiting; */ u8 phys_granted_power; * mapped into requesters via struct sci_phy.phy_index */ struct isci_phy *requesters[SCI_MAX_PHYS]; }; as comments won't start with "/*" anymore. Fix the logic to detect such cases, and keep adding the comments inside it. Signed-off-by: Mauro Carvalho Chehab Message-ID: <18e577dbbd538dcc22945ff139fe3638344e14f0.1773074166.git.mchehab+huawei@kernel.org> Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <12ac4a97e2bd5a19d6537122c10098690c38d2c7.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index edf70ba139a5..086579d00b5c 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -1355,6 +1355,12 @@ class KernelDoc: elif doc_content.search(line): self.emit_msg(ln, f"Incorrect use of kernel-doc format: {line}") self.state = state.PROTO + + # + # Don't let it add partial comments at the code, as breaks the + # logic meant to remove comments from prototypes. + # + self.process_proto_type(ln, "/**\n" + line) # else ... ?? def process_inline_text(self, ln, line): From d5265f7af2d284d5421b763f268157b5fa72f806 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:24 +0100 Subject: [PATCH 081/162] docs: kdoc: properly handle empty enum arguments Depending on how the enum proto is written, a comma at the end may incorrectly make kernel-doc parse an arg like " ". Strip spaces before checking if arg is empty. Signed-off-by: Mauro Carvalho Chehab Message-ID: <4182bfb7e5f5b4bbaf05cee1bede691e56247eaf.1773074166.git.mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet Message-ID: <640784283d52c5fc52ea597344ecd567e2fb6e22.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 086579d00b5c..4b3c555e6c8e 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -810,9 +810,10 @@ class KernelDoc: member_set = set() members = KernRe(r'\([^;)]*\)').sub('', members) for arg in members.split(','): - if not arg: - continue arg = KernRe(r'^\s*(\w+).*').sub(r'\1', arg) + if not arg.strip(): + continue + self.entry.parameterlist.append(arg) if arg not in self.entry.parameterdescs: self.entry.parameterdescs[arg] = self.undescribed From df50e848f67523195ee0b4c6d2c01823e36a15e7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:25 +0100 Subject: [PATCH 082/162] docs: add a C tokenizer to be used by kernel-doc Handling C code purely using regular expressions doesn't work well. Add a C tokenizer to help doing it the right way. The tokenizer was written using as basis the Python re documentation tokenizer example from: https://docs.python.org/3/library/re.html#writing-a-tokenizer Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <39787bb8022e10c65df40c746077f7f66d07ffed.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/c_lex.py | 292 +++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 tools/lib/python/kdoc/c_lex.py diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py new file mode 100644 index 000000000000..9d726f821f3f --- /dev/null +++ b/tools/lib/python/kdoc/c_lex.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2025: Mauro Carvalho Chehab . + +""" +Regular expression ancillary classes. + +Those help caching regular expressions and do matching for kernel-doc. + +Please notice that the code here may rise exceptions to indicate bad +usage inside kdoc to indicate problems at the replace pattern. + +Other errors are logged via log instance. +""" + +import logging +import re + +from .kdoc_re import KernRe + +log = logging.getLogger(__name__) + + +class CToken(): + """ + Data class to define a C token. + """ + + # Tokens that can be used by the parser. Works like an C enum. + + COMMENT = 0 #: A standard C or C99 comment, including delimiter. + STRING = 1 #: A string, including quotation marks. + CHAR = 2 #: A character, including apostophes. + NUMBER = 3 #: A number. + PUNC = 4 #: A puntuation mark: / ``,`` / ``.``. + BEGIN = 5 #: A begin character: ``{`` / ``[`` / ``(``. + END = 6 #: A end character: ``}`` / ``]`` / ``)``. + CPP = 7 #: A preprocessor macro. + HASH = 8 #: The hash character - useful to handle other macros. + OP = 9 #: A C operator (add, subtract, ...). + STRUCT = 10 #: A ``struct`` keyword. + UNION = 11 #: An ``union`` keyword. + ENUM = 12 #: A ``struct`` keyword. + TYPEDEF = 13 #: A ``typedef`` keyword. + NAME = 14 #: A name. Can be an ID or a type. + SPACE = 15 #: Any space characters, including new lines + ENDSTMT = 16 #: End of an statement (``;``). + + BACKREF = 17 #: Not a valid C sequence, but used at sub regex patterns. + + MISMATCH = 255 #: an error indicator: should never happen in practice. + + # Dict to convert from an enum interger into a string. + _name_by_val = {v: k for k, v in dict(vars()).items() if isinstance(v, int)} + + # Dict to convert from string to an enum-like integer value. + _name_to_val = {k: v for v, k in _name_by_val.items()} + + @staticmethod + def to_name(val): + """Convert from an integer value from CToken enum into a string""" + + return CToken._name_by_val.get(val, f"UNKNOWN({val})") + + @staticmethod + def from_name(name): + """Convert a string into a CToken enum value""" + if name in CToken._name_to_val: + return CToken._name_to_val[name] + + return CToken.MISMATCH + + + def __init__(self, kind, value=None, pos=0, + brace_level=0, paren_level=0, bracket_level=0): + self.kind = kind + self.value = value + self.pos = pos + self.level = (bracket_level, paren_level, brace_level) + + def __repr__(self): + name = self.to_name(self.kind) + if isinstance(self.value, str): + value = '"' + self.value + '"' + else: + value = self.value + + return f"CToken(CToken.{name}, {value}, {self.pos}, {self.level})" + +#: Regexes to parse C code, transforming it into tokens. +RE_SCANNER_LIST = [ + # + # Note that \s\S is different than .*, as it also catches \n + # + (CToken.COMMENT, r"//[^\n]*|/\*[\s\S]*?\*/"), + + (CToken.STRING, r'"(?:\\.|[^"\\])*"'), + (CToken.CHAR, r"'(?:\\.|[^'\\])'"), + + (CToken.NUMBER, r"0[xX][\da-fA-F]+[uUlL]*|0[0-7]+[uUlL]*|" + r"\d+(?:\.\d*)?(?:[eE][+-]?\d+)?[fFlL]*"), + + (CToken.ENDSTMT, r"(?:\s+;|;)"), + + (CToken.PUNC, r"[,\.]"), + + (CToken.BEGIN, r"[\[\(\{]"), + + (CToken.END, r"[\]\)\}]"), + + (CToken.CPP, r"#\s*(?:define|include|ifdef|ifndef|if|else|elif|endif|undef|pragma)\b"), + + (CToken.HASH, r"#"), + + (CToken.OP, r"\+\+|\-\-|\->|==|\!=|<=|>=|&&|\|\||<<|>>|\+=|\-=|\*=|/=|%=" + r"|&=|\|=|\^=|[=\+\-\*/%<>&\|\^~!\?\:]"), + + (CToken.STRUCT, r"\bstruct\b"), + (CToken.UNION, r"\bunion\b"), + (CToken.ENUM, r"\benum\b"), + (CToken.TYPEDEF, r"\btypedef\b"), + + (CToken.NAME, r"[A-Za-z_]\w*"), + + (CToken.SPACE, r"\s+"), + + (CToken.BACKREF, r"\\\d+"), + + (CToken.MISMATCH,r"."), +] + +def fill_re_scanner(token_list): + """Ancillary routine to convert RE_SCANNER_LIST into a finditer regex""" + re_tokens = [] + + for kind, pattern in token_list: + name = CToken.to_name(kind) + re_tokens.append(f"(?P<{name}>{pattern})") + + return KernRe("|".join(re_tokens), re.MULTILINE | re.DOTALL) + +#: Handle C continuation lines. +RE_CONT = KernRe(r"\\\n") + +RE_COMMENT_START = KernRe(r'/\*\s*') + +#: tokenizer regex. Will be filled at the first CTokenizer usage. +RE_SCANNER = fill_re_scanner(RE_SCANNER_LIST) + + +class CTokenizer(): + """ + Scan C statements and definitions and produce tokens. + + When converted to string, it drops comments and handle public/private + values, respecting depth. + """ + + # This class is inspired and follows the basic concepts of: + # https://docs.python.org/3/library/re.html#writing-a-tokenizer + + def __init__(self, source=None, log=None): + """ + Create a regular expression to handle RE_SCANNER_LIST. + + While I generally don't like using regex group naming via: + (?P...) + + in this particular case, it makes sense, as we can pick the name + when matching a code via RE_SCANNER. + """ + + self.tokens = [] + + if not source: + return + + if isinstance(source, list): + self.tokens = source + return + + # + # While we could just use _tokenize directly via interator, + # As we'll need to use the tokenizer several times inside kernel-doc + # to handle macro transforms, cache the results on a list, as + # re-using it is cheaper than having to parse everytime. + # + for tok in self._tokenize(source): + self.tokens.append(tok) + + def _tokenize(self, source): + """ + Iterator that parses ``source``, splitting it into tokens, as defined + at ``self.RE_SCANNER_LIST``. + + The interactor returns a CToken class object. + """ + + # Handle continuation lines. Note that kdoc_parser already has a + # logic to do that. Still, let's keep it for completeness, as we might + # end re-using this tokenizer outsize kernel-doc some day - or we may + # eventually remove from there as a future cleanup. + source = RE_CONT.sub("", source) + + brace_level = 0 + paren_level = 0 + bracket_level = 0 + + for match in RE_SCANNER.finditer(source): + kind = CToken.from_name(match.lastgroup) + pos = match.start() + value = match.group() + + if kind == CToken.MISMATCH: + log.error(f"Unexpected token '{value}' on pos {pos}:\n\t'{source}'") + elif kind == CToken.BEGIN: + if value == '(': + paren_level += 1 + elif value == '[': + bracket_level += 1 + else: # value == '{' + brace_level += 1 + + elif kind == CToken.END: + if value == ')' and paren_level > 0: + paren_level -= 1 + elif value == ']' and bracket_level > 0: + bracket_level -= 1 + elif brace_level > 0: # value == '}' + brace_level -= 1 + + yield CToken(kind, value, pos, + brace_level, paren_level, bracket_level) + + def __str__(self): + out="" + show_stack = [True] + + for i, tok in enumerate(self.tokens): + if tok.kind == CToken.BEGIN: + show_stack.append(show_stack[-1]) + + elif tok.kind == CToken.END: + prev = show_stack[-1] + if len(show_stack) > 1: + show_stack.pop() + + if not prev and show_stack[-1]: + # + # Try to preserve indent + # + out += "\t" * (len(show_stack) - 1) + + out += str(tok.value) + continue + + elif tok.kind == CToken.COMMENT: + comment = RE_COMMENT_START.sub("", tok.value) + + if comment.startswith("private:"): + show_stack[-1] = False + show = False + elif comment.startswith("public:"): + show_stack[-1] = True + + continue + + if not show_stack[-1]: + continue + + if i < len(self.tokens) - 1: + next_tok = self.tokens[i + 1] + + # Do some cleanups before ";" + + if (tok.kind == CToken.SPACE and + next_tok.kind == CToken.PUNC and + next_tok.value == ";"): + + continue + + if (tok.kind == CToken.PUNC and + next_tok.kind == CToken.PUNC and + tok.value == ";" and + next_tok.kind == CToken.PUNC and + next_tok.value == ";"): + + continue + + out += str(tok.value) + + return out From cd77a9aa20ef53a03e5bb2630a5e7b16b910f198 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:26 +0100 Subject: [PATCH 083/162] docs: kdoc: use tokenizer to handle comments on structs Better handle comments inside structs. After those changes, all unittests now pass: test_private: TestPublicPrivate: test balanced_inner_private: OK test balanced_non_greddy_private: OK test balanced_private: OK test no private: OK test unbalanced_inner_private: OK test unbalanced_private: OK test unbalanced_struct_group_tagged_with_private: OK test unbalanced_two_struct_group_tagged_first_with_private: OK test unbalanced_without_end_of_line: OK Ran 9 tests This also solves a bug when handling STRUCT_GROUP() with a private comment on it: @@ -397134,7 +397134,7 @@ basic V4L2 device-level support. unsigned int max_len; unsigned int offset; struct page_pool_params_slow slow; - STRUCT_GROUP( struct net_device *netdev; + struct net_device *netdev; unsigned int queue_idx; unsigned int flags; }; Signed-off-by: Mauro Carvalho Chehab Message-ID: Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <054763260f7b5459ad0738ed906d7c358d640692.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 4b3c555e6c8e..62d8030cf532 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -13,6 +13,7 @@ import sys import re from pprint import pformat +from kdoc.c_lex import CTokenizer from kdoc.kdoc_re import NestedMatch, KernRe from kdoc.kdoc_item import KdocItem @@ -84,15 +85,9 @@ def trim_private_members(text): """ Remove ``struct``/``enum`` members that have been marked "private". """ - # First look for a "public:" block that ends a private region, then - # handle the "private until the end" case. - # - text = KernRe(r'/\*\s*private:.*?/\*\s*public:.*?\*/', flags=re.S).sub('', text) - text = KernRe(r'/\*\s*private:.*', flags=re.S).sub('', text) - # - # We needed the comments to do the above, but now we can take them out. - # - return KernRe(r'\s*/\*.*?\*/\s*', flags=re.S).sub('', text).strip() + + tokens = CTokenizer(text) + return str(tokens) class state: """ From fe79f85fc85691b64db1997a3b1a2df5d6d378ae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:27 +0100 Subject: [PATCH 084/162] unittests: test_private: modify it to use CTokenizer directly Change the logic to use the tokenizer directly. This allows adding more unit tests to check the validty of the tokenizer itself. Signed-off-by: Mauro Carvalho Chehab Message-ID: <2672257233ff73a9464c09b50924be51e25d4f59.1773074166.git.mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet Message-ID: <66e6320a4d5ad9730c1c0ceea79b5021e90c66c6.1773770483.git.mchehab+huawei@kernel.org> --- .../{test_private.py => test_tokenizer.py} | 75 +++++++++++++------ 1 file changed, 51 insertions(+), 24 deletions(-) rename tools/unittests/{test_private.py => test_tokenizer.py} (85%) diff --git a/tools/unittests/test_private.py b/tools/unittests/test_tokenizer.py similarity index 85% rename from tools/unittests/test_private.py rename to tools/unittests/test_tokenizer.py index eae245ae8a12..3b1d0b5bd311 100755 --- a/tools/unittests/test_private.py +++ b/tools/unittests/test_tokenizer.py @@ -15,20 +15,43 @@ from unittest.mock import MagicMock SRC_DIR = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) -from kdoc.kdoc_parser import trim_private_members +from kdoc.c_lex import CTokenizer from unittest_helper import run_unittest + # # List of tests. # # The code will dynamically generate one test for each key on this dictionary. # +def make_private_test(name, data): + """ + Create a test named ``name`` using parameters given by ``data`` dict. + """ + + def test(self): + """In-lined lambda-like function to run the test""" + tokens = CTokenizer(data["source"]) + result = str(tokens) + + # + # Avoid whitespace false positives + # + result = re.sub(r"\s++", " ", result).strip() + expected = re.sub(r"\s++", " ", data["trimmed"]).strip() + + msg = f"failed when parsing this source:\n{data['source']}" + self.assertEqual(result, expected, msg=msg) + + return test + #: Tests to check if CTokenizer is handling properly public/private comments. TESTS_PRIVATE = { # # Simplest case: no private. Ensure that trimming won't affect struct # + "__run__": make_private_test, "no private": { "source": """ struct foo { @@ -288,41 +311,45 @@ TESTS_PRIVATE = { }, } +#: Dict containing all test groups fror CTokenizer +TESTS = { + "TestPublicPrivate": TESTS_PRIVATE, +} -class TestPublicPrivate(unittest.TestCase): +def setUp(self): + self.maxDiff = None + +def build_test_class(group_name, table): """ - Main test class. Populated dynamically at runtime. + Dynamically creates a class instance using type() as a generator + for a new class derivated from unittest.TestCase. + + We're opting to do it inside a function to avoid the risk of + changing the globals() dictionary. """ - def setUp(self): - self.maxDiff = None + class_dict = { + "setUp": setUp + } - def add_test(cls, name, source, trimmed): - """ - Dynamically add a test to the class - """ - def test(cls): - result = trim_private_members(source) + run = table["__run__"] - result = re.sub(r"\s++", " ", result).strip() - expected = re.sub(r"\s++", " ", trimmed).strip() + for test_name, data in table.items(): + if test_name == "__run__": + continue - msg = f"failed when parsing this source:\n" + source + class_dict[f"test_{test_name}"] = run(test_name, data) - cls.assertEqual(result, expected, msg=msg) - - test.__name__ = f'test {name}' - - setattr(TestPublicPrivate, test.__name__, test) + cls = type(group_name, (unittest.TestCase,), class_dict) + return cls.__name__, cls # -# Populate TestPublicPrivate class +# Create classes and add them to the global dictionary # -test_class = TestPublicPrivate() -for name, test in TESTS_PRIVATE.items(): - test_class.add_test(name, test["source"], test["trimmed"]) - +for group, table in TESTS.items(): + t = build_test_class(group, table) + globals()[t[0]] = t[1] # # main From 5f6fc8ed4933760c2bcddb86460fe45ada1b943c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:28 +0100 Subject: [PATCH 085/162] unittests: test_tokenizer: check if the tokenizer works Add extra tests to check if the tokenizer is working properly. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/unittests/test_tokenizer.py | 108 +++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 2 deletions(-) diff --git a/tools/unittests/test_tokenizer.py b/tools/unittests/test_tokenizer.py index 3b1d0b5bd311..5634b4a7283e 100755 --- a/tools/unittests/test_tokenizer.py +++ b/tools/unittests/test_tokenizer.py @@ -15,15 +15,118 @@ from unittest.mock import MagicMock SRC_DIR = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) -from kdoc.c_lex import CTokenizer +from kdoc.c_lex import CToken, CTokenizer from unittest_helper import run_unittest - # # List of tests. # # The code will dynamically generate one test for each key on this dictionary. # +def tokens_to_list(tokens): + tuples = [] + + for tok in tokens: + if tok.kind == CToken.SPACE: + continue + + tuples += [(tok.kind, tok.value, tok.level)] + + return tuples + + +def make_tokenizer_test(name, data): + """ + Create a test named ``name`` using parameters given by ``data`` dict. + """ + + def test(self): + """In-lined lambda-like function to run the test""" + + # + # Check if logger is working + # + if "log_level" in data: + with self.assertLogs('kdoc.c_lex', level='ERROR') as cm: + tokenizer = CTokenizer(data["source"]) + + return + + # + # Check if tokenizer is producing expected results + # + tokens = CTokenizer(data["source"]).tokens + + result = tokens_to_list(tokens) + expected = tokens_to_list(data["expected"]) + + self.assertEqual(result, expected, msg=f"{name}") + + return test + +#: Tokenizer tests. +TESTS_TOKENIZER = { + "__run__": make_tokenizer_test, + + "basic_tokens": { + "source": """ + int a; // comment + float b = 1.23; + """, + "expected": [ + CToken(CToken.NAME, "int"), + CToken(CToken.NAME, "a"), + CToken(CToken.ENDSTMT, ";"), + CToken(CToken.COMMENT, "// comment"), + CToken(CToken.NAME, "float"), + CToken(CToken.NAME, "b"), + CToken(CToken.OP, "="), + CToken(CToken.NUMBER, "1.23"), + CToken(CToken.ENDSTMT, ";"), + ], + }, + + "depth_counters": { + "source": """ + struct X { + int arr[10]; + func(a[0], (b + c)); + } + """, + "expected": [ + CToken(CToken.STRUCT, "struct"), + CToken(CToken.NAME, "X"), + CToken(CToken.BEGIN, "{", brace_level=1), + + CToken(CToken.NAME, "int", brace_level=1), + CToken(CToken.NAME, "arr", brace_level=1), + CToken(CToken.BEGIN, "[", brace_level=1, bracket_level=1), + CToken(CToken.NUMBER, "10", brace_level=1, bracket_level=1), + CToken(CToken.END, "]", brace_level=1), + CToken(CToken.ENDSTMT, ";", brace_level=1), + CToken(CToken.NAME, "func", brace_level=1), + CToken(CToken.BEGIN, "(", brace_level=1, paren_level=1), + CToken(CToken.NAME, "a", brace_level=1, paren_level=1), + CToken(CToken.BEGIN, "[", brace_level=1, paren_level=1, bracket_level=1), + CToken(CToken.NUMBER, "0", brace_level=1, paren_level=1, bracket_level=1), + CToken(CToken.END, "]", brace_level=1, paren_level=1), + CToken(CToken.PUNC, ",", brace_level=1, paren_level=1), + CToken(CToken.BEGIN, "(", brace_level=1, paren_level=2), + CToken(CToken.NAME, "b", brace_level=1, paren_level=2), + CToken(CToken.OP, "+", brace_level=1, paren_level=2), + CToken(CToken.NAME, "c", brace_level=1, paren_level=2), + CToken(CToken.END, ")", brace_level=1, paren_level=1), + CToken(CToken.END, ")", brace_level=1), + CToken(CToken.ENDSTMT, ";", brace_level=1), + CToken(CToken.END, "}"), + ], + }, + + "mismatch_error": { + "source": "int a$ = 5;", # $ is illegal + "log_level": "ERROR", + }, +} def make_private_test(name, data): """ @@ -314,6 +417,7 @@ TESTS_PRIVATE = { #: Dict containing all test groups fror CTokenizer TESTS = { "TestPublicPrivate": TESTS_PRIVATE, + "TestTokenizer": TESTS_TOKENIZER, } def setUp(self): From bd167a2122600ac787913275ad1eb5dd38698d9f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:29 +0100 Subject: [PATCH 086/162] unittests: add a runner to execute all unittests We'll soon have multiple unit tests, add a runner that will discover all of them and execute all tests. It was opted to discover only files that starts with "test", as this way unittest discover won't try adding libraries or other stuff that might not contain unittest classes. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <2d9dd14f03d3d6394346fdaceeb3167d54d1dd0c.1773770483.git.mchehab+huawei@kernel.org> --- tools/unittests/run.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 tools/unittests/run.py diff --git a/tools/unittests/run.py b/tools/unittests/run.py new file mode 100755 index 000000000000..8c19036d43a1 --- /dev/null +++ b/tools/unittests/run.py @@ -0,0 +1,17 @@ +#!/bin/env python3 +import os +import unittest +import sys + +TOOLS_DIR=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..") +sys.path.insert(0, TOOLS_DIR) + +from lib.python.unittest_helper import TestUnits + +if __name__ == "__main__": + loader = unittest.TestLoader() + + suite = loader.discover(start_dir=os.path.join(TOOLS_DIR, "unittests"), + pattern="test*.py") + + TestUnits().run("", suite=suite) From f1cf9f7cd66f1f90c4c3beb0885b6f7771e1b419 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:30 +0100 Subject: [PATCH 087/162] docs: kdoc: create a CMatch to match nested C blocks The NextMatch code is complex, and will become even more complex if we add there support for arguments. Now that we have a tokenizer, we can use a better solution, easier to be understood. Yet, to improve performance, it is better to make it use a previously tokenized code, changing its ABI. So, reimplement NextMatch using the CTokener class. Once it is done, we can drop NestedMatch. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/c_lex.py | 121 ++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 10 deletions(-) diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py index 9d726f821f3f..5da472734ff7 100644 --- a/tools/lib/python/kdoc/c_lex.py +++ b/tools/lib/python/kdoc/c_lex.py @@ -273,20 +273,121 @@ class CTokenizer(): # Do some cleanups before ";" - if (tok.kind == CToken.SPACE and - next_tok.kind == CToken.PUNC and - next_tok.value == ";"): - + if tok.kind == CToken.SPACE and next_tok.kind == CToken.ENDSTMT: continue - if (tok.kind == CToken.PUNC and - next_tok.kind == CToken.PUNC and - tok.value == ";" and - next_tok.kind == CToken.PUNC and - next_tok.value == ";"): - + if tok.kind == CToken.ENDSTMT and next_tok.kind == tok.kind: continue out += str(tok.value) return out + + +class CMatch: + """ + Finding nested delimiters is hard with regular expressions. It is + even harder on Python with its normal re module, as there are several + advanced regular expressions that are missing. + + This is the case of this pattern:: + + '\\bSTRUCT_GROUP(\\(((?:(?>[^)(]+)|(?1))*)\\))[^;]*;' + + which is used to properly match open/close parentheses of the + string search STRUCT_GROUP(), + + Add a class that counts pairs of delimiters, using it to match and + replace nested expressions. + + The original approach was suggested by: + + https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex + + Although I re-implemented it to make it more generic and match 3 types + of delimiters. The logic checks if delimiters are paired. If not, it + will ignore the search string. + """ + + # TODO: add a sub method + + def __init__(self, regex): + self.regex = KernRe(regex) + + def _search(self, tokenizer): + """ + Finds paired blocks for a regex that ends with a delimiter. + + The suggestion of using finditer to match pairs came from: + https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex + but I ended using a different implementation to align all three types + of delimiters and seek for an initial regular expression. + + The algorithm seeks for open/close paired delimiters and places them + into a stack, yielding a start/stop position of each match when the + stack is zeroed. + + The algorithm should work fine for properly paired lines, but will + silently ignore end delimiters that precede a start delimiter. + This should be OK for kernel-doc parser, as unaligned delimiters + would cause compilation errors. So, we don't need to raise exceptions + to cover such issues. + """ + + start = None + offset = -1 + started = False + + import sys + + stack = [] + + for i, tok in enumerate(tokenizer.tokens): + if start is None: + if tok.kind == CToken.NAME and self.regex.match(tok.value): + start = i + stack.append((start, tok.level)) + started = False + + continue + + if not started and tok.kind == CToken.BEGIN: + started = True + continue + + if tok.kind == CToken.END and tok.level == stack[-1][1]: + start, level = stack.pop() + offset = i + + yield CTokenizer(tokenizer.tokens[start:offset + 1]) + start = None + + # + # If an END zeroing levels is not there, return remaining stuff + # This is meant to solve cases where the caller logic might be + # picking an incomplete block. + # + if start and offset < 0: + print("WARNING: can't find an end", file=sys.stderr) + yield CTokenizer(tokenizer.tokens[start:]) + + def search(self, source): + """ + This is similar to re.search: + + It matches a regex that it is followed by a delimiter, + returning occurrences only if all delimiters are paired. + """ + + if isinstance(source, CTokenizer): + tokenizer = source + is_token = True + else: + tokenizer = CTokenizer(source) + is_token = False + + for new_tokenizer in self._search(tokenizer): + if is_token: + yield new_tokenizer + else: + yield str(new_tokenizer) From 50b87bb41e48127ec43a35f9302abb4c63ca6cc9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:31 +0100 Subject: [PATCH 088/162] tools: unittests: add tests for CMatch The CMatch logic is complex enough to justify tests to ensure that it is doing its job. Add unittests to check the functionality provided by CMatch by replicating expected patterns. The CMatch class handles with complex macros. Add an unittest to check if its doing the right thing and detect eventual regressions as we improve its code. The initial version was generated using gpt-oss:latest LLM on my local GPU, as LLMs aren't bad transforming patterns into unittests. Yet, the curent version contains only the skeleton of what LLM produced, as I ended higly changing its content to be more representative and to have real case scenarios. The kdoc_xforms test suite contains 3 test groups. Two of them tests the basic functionality of CMatch to replace patterns. The last one (TestRealUsecases) contains real code snippets from the Kernel with some cleanups to better fit in 80 columns and uses the same transforms as kernel-doc, thus allowing to test the logic used inside kdoc_parser to transform functions, structs and variable patterns. Its output is like this: $ tools/unittests/kdoc_xforms.py Ran 25 tests in 0.003s OK test_cmatch: TestSearch: test_search_acquires_multiple: OK test_search_acquires_nested_paren: OK test_search_acquires_simple: OK test_search_must_hold: OK test_search_must_hold_shared: OK test_search_no_false_positive: OK test_search_no_function: OK test_search_no_macro_remains: OK Ran 8 tests Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <119712b5bc53b4c6dda6a81b4a783dcbfd1d970d.1773770483.git.mchehab+huawei@kernel.org> --- tools/unittests/test_cmatch.py | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 tools/unittests/test_cmatch.py diff --git a/tools/unittests/test_cmatch.py b/tools/unittests/test_cmatch.py new file mode 100755 index 000000000000..53b25aa4dc4a --- /dev/null +++ b/tools/unittests/test_cmatch.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . +# +# pylint: disable=C0413,R0904 + + +""" +Unit tests for kernel-doc CMatch. +""" + +import os +import re +import sys +import unittest + + +# Import Python modules + +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) + +from kdoc.c_lex import CMatch +from kdoc.xforms_lists import CTransforms +from unittest_helper import run_unittest + +# +# Override unittest.TestCase to better compare diffs ignoring whitespaces +# +class TestCaseDiff(unittest.TestCase): + """ + Disable maximum limit on diffs and add a method to better + handle diffs with whitespace differences. + """ + + @classmethod + def setUpClass(cls): + """Ensure that there won't be limit for diffs""" + cls.maxDiff = None + + +# +# Tests doing with different macros +# + +class TestSearch(TestCaseDiff): + """ + Test search mechanism + """ + + def test_search_acquires_simple(self): + line = "__acquires(ctx) foo();" + result = ", ".join(CMatch("__acquires").search(line)) + self.assertEqual(result, "__acquires(ctx)") + + def test_search_acquires_multiple(self): + line = "__acquires(ctx) __acquires(other) bar();" + result = ", ".join(CMatch("__acquires").search(line)) + self.assertEqual(result, "__acquires(ctx), __acquires(other)") + + def test_search_acquires_nested_paren(self): + line = "__acquires((ctx1, ctx2)) baz();" + result = ", ".join(CMatch("__acquires").search(line)) + self.assertEqual(result, "__acquires((ctx1, ctx2))") + + def test_search_must_hold(self): + line = "__must_hold(&lock) do_something();" + result = ", ".join(CMatch("__must_hold").search(line)) + self.assertEqual(result, "__must_hold(&lock)") + + def test_search_must_hold_shared(self): + line = "__must_hold_shared(RCU) other();" + result = ", ".join(CMatch("__must_hold_shared").search(line)) + self.assertEqual(result, "__must_hold_shared(RCU)") + + def test_search_no_false_positive(self): + line = "call__acquires(foo); // should stay intact" + result = ", ".join(CMatch(r"\b__acquires").search(line)) + self.assertEqual(result, "") + + def test_search_no_macro_remains(self): + line = "do_something_else();" + result = ", ".join(CMatch("__acquires").search(line)) + self.assertEqual(result, "") + + def test_search_no_function(self): + line = "something" + result = ", ".join(CMatch(line).search(line)) + self.assertEqual(result, "") + +# +# Run all tests +# +if __name__ == "__main__": + run_unittest(__file__) From 9aaeb817ef4f794d1dbb8736332a64b5dae9521c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:32 +0100 Subject: [PATCH 089/162] docs: c_lex: properly implement a sub() method for CMatch Implement a sub() method to do what it is expected, parsing backref arguments like \0, \1, \2, ... Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/c_lex.py | 272 +++++++++++++++++++++++++++++++-- 1 file changed, 259 insertions(+), 13 deletions(-) diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py index 5da472734ff7..20e50ff0ecd5 100644 --- a/tools/lib/python/kdoc/c_lex.py +++ b/tools/lib/python/kdoc/c_lex.py @@ -16,6 +16,8 @@ Other errors are logged via log instance. import logging import re +from copy import copy + from .kdoc_re import KernRe log = logging.getLogger(__name__) @@ -284,6 +286,172 @@ class CTokenizer(): return out +class CTokenArgs: + """ + Ancillary class to help using backrefs from sub matches. + + If the highest backref contain a "+" at the last element, + the logic will be greedy, picking all other delims. + + This is needed to parse struct_group macros with end with ``MEMBERS...``. + """ + def __init__(self, sub_str): + self.sub_groups = set() + self.max_group = -1 + self.greedy = None + + for m in KernRe(r'\\(\d+)([+]?)').finditer(sub_str): + group = int(m.group(1)) + if m.group(2) == "+": + if self.greedy and self.greedy != group: + raise ValueError("There are multiple greedy patterns!") + self.greedy = group + + self.sub_groups.add(group) + self.max_group = max(self.max_group, group) + + if self.greedy: + if self.greedy != self.max_group: + raise ValueError("Greedy pattern is not the last one!") + + sub_str = KernRe(r'(\\\d+)[+]').sub(r"\1", sub_str) + + self.sub_str = sub_str + self.sub_tokeninzer = CTokenizer(sub_str) + + def groups(self, new_tokenizer): + """ + Create replacement arguments for backrefs like: + + ``\0``, ``\1``, ``\2``, ...``\n`` + + It also accepts a ``+`` character to the highest backref. When used, + it means in practice to ignore delimins after it, being greedy. + + The logic is smart enough to only go up to the maximum required + argument, even if there are more. + + If there is a backref for an argument above the limit, it will + raise an exception. Please notice that, on C, square brackets + don't have any separator on it. Trying to use ``\1``..``\n`` for + brackets also raise an exception. + """ + + level = (0, 0, 0) + + if self.max_group < 0: + return level, [] + + tokens = new_tokenizer.tokens + + # + # Fill \0 with the full token contents + # + groups_list = [ [] ] + + if 0 in self.sub_groups: + inner_level = 0 + + for i in range(0, len(tokens)): + tok = tokens[i] + + if tok.kind == CToken.BEGIN: + inner_level += 1 + + # + # Discard first begin + # + if not groups_list[0]: + continue + elif tok.kind == CToken.END: + inner_level -= 1 + if inner_level < 0: + break + + if inner_level: + groups_list[0].append(tok) + + if not self.max_group: + return level, groups_list + + delim = None + + # + # Ignore everything before BEGIN. The value of begin gives the + # delimiter to be used for the matches + # + for i in range(0, len(tokens)): + tok = tokens[i] + if tok.kind == CToken.BEGIN: + if tok.value == "{": + delim = ";" + elif tok.value == "(": + delim = "," + else: + self.log.error(fr"Can't handle \1..\n on {sub_str}") + + level = tok.level + break + + pos = 1 + groups_list.append([]) + + inner_level = 0 + for i in range(i + 1, len(tokens)): + tok = tokens[i] + + if tok.kind == CToken.BEGIN: + inner_level += 1 + if tok.kind == CToken.END: + inner_level -= 1 + if inner_level < 0: + break + + if tok.kind in [CToken.PUNC, CToken.ENDSTMT] and delim == tok.value: + pos += 1 + if self.greedy and pos > self.max_group: + pos -= 1 + else: + groups_list.append([]) + + if pos > self.max_group: + break + + continue + + groups_list[pos].append(tok) + + if pos < self.max_group: + log.error(fr"{self.sub_str} groups are up to {pos} instead of {self.max_group}") + + return level, groups_list + + def tokens(self, new_tokenizer): + level, groups = self.groups(new_tokenizer) + + new = CTokenizer() + + for tok in self.sub_tokeninzer.tokens: + if tok.kind == CToken.BACKREF: + group = int(tok.value[1:]) + + for group_tok in groups[group]: + new_tok = copy(group_tok) + + new_level = [0, 0, 0] + + for i in range(0, len(level)): + new_level[i] = new_tok.level[i] + level[i] + + new_tok.level = tuple(new_level) + + new.tokens += [ new_tok ] + else: + new.tokens += [ tok ] + + return new.tokens + + class CMatch: """ Finding nested delimiters is hard with regular expressions. It is @@ -309,10 +477,10 @@ class CMatch: will ignore the search string. """ - # TODO: add a sub method - def __init__(self, regex): - self.regex = KernRe(regex) + def __init__(self, regex, delim="("): + self.regex = KernRe("^" + regex + r"\b") + self.start_delim = delim def _search(self, tokenizer): """ @@ -335,7 +503,6 @@ class CMatch: """ start = None - offset = -1 started = False import sys @@ -351,15 +518,24 @@ class CMatch: continue - if not started and tok.kind == CToken.BEGIN: - started = True - continue + if not started: + if tok.kind == CToken.SPACE: + continue + + if tok.kind == CToken.BEGIN and tok.value == self.start_delim: + started = True + continue + + # Name only token without BEGIN/END + if i > start: + i -= 1 + yield start, i + start = None if tok.kind == CToken.END and tok.level == stack[-1][1]: start, level = stack.pop() - offset = i - yield CTokenizer(tokenizer.tokens[start:offset + 1]) + yield start, i start = None # @@ -367,9 +543,12 @@ class CMatch: # This is meant to solve cases where the caller logic might be # picking an incomplete block. # - if start and offset < 0: - print("WARNING: can't find an end", file=sys.stderr) - yield CTokenizer(tokenizer.tokens[start:]) + if start and stack: + if started: + s = str(tokenizer) + log.warning(f"can't find a final end at {s}") + + yield start, len(tokenizer.tokens) def search(self, source): """ @@ -386,8 +565,75 @@ class CMatch: tokenizer = CTokenizer(source) is_token = False - for new_tokenizer in self._search(tokenizer): + for start, end in self._search(tokenizer): + new_tokenizer = CTokenizer(tokenizer.tokens[start:end + 1]) + if is_token: yield new_tokenizer else: yield str(new_tokenizer) + + def sub(self, sub_str, source, count=0): + """ + This is similar to re.sub: + + It matches a regex that it is followed by a delimiter, + replacing occurrences only if all delimiters are paired. + + if the sub argument contains:: + + r'\0' + + it will work just like re: it places there the matched paired data + with the delimiter stripped. + + If count is different than zero, it will replace at most count + items. + """ + if isinstance(source, CTokenizer): + is_token = True + tokenizer = source + else: + is_token = False + tokenizer = CTokenizer(source) + + # Detect if sub_str contains sub arguments + + args_match = CTokenArgs(sub_str) + + new_tokenizer = CTokenizer() + pos = 0 + n = 0 + + # + # NOTE: the code below doesn't consider overlays at sub. + # We may need to add some extra unit tests to check if those + # would cause problems. When replacing by "", this should not + # be a problem, but other transformations could be problematic + # + for start, end in self._search(tokenizer): + new_tokenizer.tokens += tokenizer.tokens[pos:start] + + new = CTokenizer(tokenizer.tokens[start:end + 1]) + + new_tokenizer.tokens += args_match.tokens(new) + + pos = end + 1 + + n += 1 + if count and n >= count: + break + + new_tokenizer.tokens += tokenizer.tokens[pos:] + + if not is_token: + return str(new_tokenizer) + + return new_tokenizer + + def __repr__(self): + """ + Returns a displayable version of the class init. + """ + + return f'CMatch("{self.regex.regex.pattern}")' From c22aa12c766f087d197fab7bda81554e4c1c7a0c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:33 +0100 Subject: [PATCH 090/162] unittests: test_cmatch: add tests for sub() Now that we have code for sub(), test it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/unittests/test_cmatch.py | 730 ++++++++++++++++++++++++++++++++- 1 file changed, 728 insertions(+), 2 deletions(-) diff --git a/tools/unittests/test_cmatch.py b/tools/unittests/test_cmatch.py index 53b25aa4dc4a..7b996f83784d 100755 --- a/tools/unittests/test_cmatch.py +++ b/tools/unittests/test_cmatch.py @@ -21,7 +21,7 @@ SRC_DIR = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) from kdoc.c_lex import CMatch -from kdoc.xforms_lists import CTransforms +from kdoc.kdoc_re import KernRe from unittest_helper import run_unittest # @@ -75,7 +75,7 @@ class TestSearch(TestCaseDiff): def test_search_no_false_positive(self): line = "call__acquires(foo); // should stay intact" - result = ", ".join(CMatch(r"\b__acquires").search(line)) + result = ", ".join(CMatch(r"__acquires").search(line)) self.assertEqual(result, "") def test_search_no_macro_remains(self): @@ -88,6 +88,732 @@ class TestSearch(TestCaseDiff): result = ", ".join(CMatch(line).search(line)) self.assertEqual(result, "") +# +# Override unittest.TestCase to better compare diffs ignoring whitespaces +# +class TestCaseDiff(unittest.TestCase): + """ + Disable maximum limit on diffs and add a method to better + handle diffs with whitespace differences. + """ + + @classmethod + def setUpClass(cls): + """Ensure that there won't be limit for diffs""" + cls.maxDiff = None + + def assertLogicallyEqual(self, a, b): + """ + Compare two results ignoring multiple whitespace differences. + + This is useful to check more complex matches picked from examples. + On a plus side, we also don't need to use dedent. + Please notice that line breaks still need to match. We might + remove it at the regex, but this way, checking the diff is easier. + """ + a = re.sub(r"[\t ]+", " ", a.strip()) + b = re.sub(r"[\t ]+", " ", b.strip()) + + a = re.sub(r"\s+\n", "\n", a) + b = re.sub(r"\s+\n", "\n", b) + + a = re.sub(" ;", ";", a) + b = re.sub(" ;", ";", b) + + self.assertEqual(a, b) + +# +# Tests doing with different macros +# + +class TestSubMultipleMacros(TestCaseDiff): + """ + Tests doing with different macros. + + Here, we won't use assertLogicallyEqual. Instead, we'll check if each + of the expected patterns are present at the answer. + """ + + def test_acquires_simple(self): + """Simple replacement test with __acquires""" + line = "__acquires(ctx) foo();" + result = CMatch(r"__acquires").sub("REPLACED", line) + + self.assertEqual("REPLACED foo();", result) + + def test_acquires_multiple(self): + """Multiple __acquires""" + line = "__acquires(ctx) __acquires(other) bar();" + result = CMatch(r"__acquires").sub("REPLACED", line) + + self.assertEqual("REPLACED REPLACED bar();", result) + + def test_acquires_nested_paren(self): + """__acquires with nested pattern""" + line = "__acquires((ctx1, ctx2)) baz();" + result = CMatch(r"__acquires").sub("REPLACED", line) + + self.assertEqual("REPLACED baz();", result) + + def test_must_hold(self): + """__must_hold with a pointer""" + line = "__must_hold(&lock) do_something();" + result = CMatch(r"__must_hold").sub("REPLACED", line) + + self.assertNotIn("__must_hold(", result) + self.assertIn("do_something();", result) + + def test_must_hold_shared(self): + """__must_hold with an upercase defined value""" + line = "__must_hold_shared(RCU) other();" + result = CMatch(r"__must_hold_shared").sub("REPLACED", line) + + self.assertNotIn("__must_hold_shared(", result) + self.assertIn("other();", result) + + def test_no_false_positive(self): + """ + Ensure that unrelated text containing similar patterns is preserved + """ + line = "call__acquires(foo); // should stay intact" + result = CMatch(r"\b__acquires").sub("REPLACED", line) + + self.assertLogicallyEqual(result, "call__acquires(foo);") + + def test_mixed_macros(self): + """Add a mix of macros""" + line = "__acquires(ctx) __releases(ctx) __must_hold(&lock) foo();" + + result = CMatch(r"__acquires").sub("REPLACED", line) + result = CMatch(r"__releases").sub("REPLACED", result) + result = CMatch(r"__must_hold").sub("REPLACED", result) + + self.assertNotIn("__acquires(", result) + self.assertNotIn("__releases(", result) + self.assertNotIn("__must_hold(", result) + + self.assertIn("foo();", result) + + def test_no_macro_remains(self): + """Ensures that unmatched macros are untouched""" + line = "do_something_else();" + result = CMatch(r"__acquires").sub("REPLACED", line) + + self.assertEqual(result, line) + + def test_no_function(self): + """Ensures that no functions will remain untouched""" + line = "something" + result = CMatch(line).sub("REPLACED", line) + + self.assertEqual(result, line) + +# +# Check if the diff is logically equivalent. To simplify, the tests here +# use a single macro name for all replacements. +# + +class TestSubSimple(TestCaseDiff): + """ + Test argument replacements. + + Here, the function name can be anything. So, we picked __attribute__(), + to mimic a macro found at the Kernel, but none of the replacements her + has any relationship with the Kernel usage. + """ + + MACRO = "__attribute__" + + @classmethod + def setUpClass(cls): + """Define a CMatch to be used for all tests""" + cls.matcher = CMatch(cls.MACRO) + + def test_sub_with_capture(self): + """Test all arguments replacement with a single arg""" + line = f"{self.MACRO}(&ctx)\nfoo();" + + result = self.matcher.sub(r"ACQUIRED(\0)", line) + + self.assertLogicallyEqual("ACQUIRED(&ctx)\nfoo();", result) + + def test_sub_zero_placeholder(self): + """Test all arguments replacement with a multiple args""" + line = f"{self.MACRO}(arg1, arg2)\nbar();" + + result = self.matcher.sub(r"REPLACED(\0)", line) + + self.assertLogicallyEqual("REPLACED(arg1, arg2)\nbar();", result) + + def test_sub_single_placeholder(self): + """Single replacement rule for \1""" + line = f"{self.MACRO}(ctx, boo)\nfoo();" + result = self.matcher.sub(r"ACQUIRED(\1)", line) + + self.assertLogicallyEqual("ACQUIRED(ctx)\nfoo();", result) + + def test_sub_multiple_placeholders(self): + """Replacement rule for both \1 and \2""" + line = f"{self.MACRO}(arg1, arg2)\nbar();" + result = self.matcher.sub(r"REPLACE(\1, \2)", line) + + self.assertLogicallyEqual("REPLACE(arg1, arg2)\nbar();", result) + + def test_sub_mixed_placeholders(self): + """Replacement rule for \0, \1 and additional text""" + line = f"{self.MACRO}(foo, bar)\nbaz();" + result = self.matcher.sub(r"ALL(\0) FIRST(\1)", line) + + self.assertLogicallyEqual("ALL(foo, bar) FIRST(foo)\nbaz();", result) + + def test_sub_no_placeholder(self): + """Replacement without placeholders""" + line = f"{self.MACRO}(arg)\nfoo();" + result = self.matcher.sub(r"NO_BACKREFS()", line) + + self.assertLogicallyEqual("NO_BACKREFS()\nfoo();", result) + + def test_sub_count_parameter(self): + """Verify that the algorithm stops after the requested count""" + line = f"{self.MACRO}(a1) x();\n{self.MACRO}(a2) y();" + result = self.matcher.sub(r"ONLY_FIRST(\1) ", line, count=1) + + self.assertLogicallyEqual(f"ONLY_FIRST(a1) x();\n{self.MACRO}(a2) y();", + result) + + def test_strip_multiple_acquires(self): + """Check if spaces between removed delimiters will be dropped""" + line = f"int {self.MACRO}(1) {self.MACRO}(2 ) {self.MACRO}(3) foo;" + result = self.matcher.sub("", line) + + self.assertLogicallyEqual(result, "int foo;") + + def test_rise_early_greedy(self): + line = f"{self.MACRO}(a, b, c, d);" + sub = r"\1, \2+, \3" + + with self.assertRaises(ValueError): + result = self.matcher.sub(sub, line) + + def test_rise_multiple_greedy(self): + line = f"{self.MACRO}(a, b, c, d);" + sub = r"\1, \2+, \3+" + + with self.assertRaises(ValueError): + result = self.matcher.sub(sub, line) + +# +# Test replacements with slashrefs +# + + +class TestSubWithLocalXforms(TestCaseDiff): + """ + Test diferent usecase patterns found at the Kernel. + + Here, replacements using both CMatch and KernRe can be tested, + as it will import the actual replacement rules used by kernel-doc. + """ + + struct_xforms = [ + (CMatch("__attribute__"), ' '), + (CMatch('__aligned'), ' '), + (CMatch('__counted_by'), ' '), + (CMatch('__counted_by_(le|be)'), ' '), + (CMatch('__guarded_by'), ' '), + (CMatch('__pt_guarded_by'), ' '), + + (CMatch('__cacheline_group_(begin|end)'), ''), + + (CMatch('struct_group'), r'\2'), + (CMatch('struct_group_attr'), r'\3'), + (CMatch('struct_group_tagged'), r'struct \1 { \3+ } \2;'), + (CMatch('__struct_group'), r'\4'), + + (CMatch('__ETHTOOL_DECLARE_LINK_MODE_MASK'), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), + (CMatch('DECLARE_PHY_INTERFACE_MASK',), r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), + (CMatch('DECLARE_BITMAP'), r'unsigned long \1[BITS_TO_LONGS(\2)]'), + + (CMatch('DECLARE_HASHTABLE'), r'unsigned long \1[1 << ((\2) - 1)]'), + (CMatch('DECLARE_KFIFO'), r'\2 *\1'), + (CMatch('DECLARE_KFIFO_PTR'), r'\2 *\1'), + (CMatch('(?:__)?DECLARE_FLEX_ARRAY'), r'\1 \2[]'), + (CMatch('DEFINE_DMA_UNMAP_ADDR'), r'dma_addr_t \1'), + (CMatch('DEFINE_DMA_UNMAP_LEN'), r'__u32 \1'), + (CMatch('VIRTIO_DECLARE_FEATURES'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), + ] + + function_xforms = [ + (CMatch('__printf'), ""), + (CMatch('__(?:re)?alloc_size'), ""), + (CMatch("__diagnose_as"), ""), + (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), + + (CMatch("__cond_acquires"), ""), + (CMatch("__cond_releases"), ""), + (CMatch("__acquires"), ""), + (CMatch("__releases"), ""), + (CMatch("__must_hold"), ""), + (CMatch("__must_not_hold"), ""), + (CMatch("__must_hold_shared"), ""), + (CMatch("__cond_acquires_shared"), ""), + (CMatch("__acquires_shared"), ""), + (CMatch("__releases_shared"), ""), + (CMatch("__attribute__"), ""), + ] + + var_xforms = [ + (CMatch('__guarded_by'), ""), + (CMatch('__pt_guarded_by'), ""), + (CMatch("LIST_HEAD"), r"struct list_head \1"), + ] + + #: Transforms main dictionary used at apply_transforms(). + xforms = { + "struct": struct_xforms, + "func": function_xforms, + "var": var_xforms, + } + + @classmethod + def apply_transforms(cls, xform_type, text): + """ + Mimic the behavior of kdoc_parser.apply_transforms() method. + + For each element of STRUCT_XFORMS, apply apply_transforms. + + There are two parameters: + + - ``xform_type`` + Can be ``func``, ``struct`` or ``var``; + - ``text`` + The text where the sub patterns from CTransforms will be applied. + """ + for search, subst in cls.xforms.get(xform_type): + text = search.sub(subst, text) + + return text.strip() + + cls.matcher = CMatch(r"struct_group[\w\_]*") + + def test_struct_group(self): + """ + Test struct_group using a pattern from + drivers/net/ethernet/asix/ax88796c_main.h. + """ + line = """ + struct tx_pkt_info { + struct_group(tx_overhead, + struct tx_sop_header sop; + struct tx_segment_header seg; + ); + struct tx_eop_header eop; + u16 pkt_len; + u16 seq_num; + }; + """ + expected = """ + struct tx_pkt_info { + struct tx_sop_header sop; + struct tx_segment_header seg; + struct tx_eop_header eop; + u16 pkt_len; + u16 seq_num; + }; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_struct_group_attr(self): + """ + Test two struct_group_attr using patterns from fs/smb/client/cifspdu.h. + """ + line = """ + typedef struct smb_com_open_rsp { + struct smb_hdr hdr; /* wct = 34 BB */ + __u8 AndXCommand; + __u8 AndXReserved; + __le16 AndXOffset; + __u8 OplockLevel; + __u16 Fid; + __le32 CreateAction; + struct_group_attr(common_attributes,, + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 FileAttributes; + ); + __le64 AllocationSize; + __le64 EndOfFile; + __le16 FileType; + __le16 DeviceState; + __u8 DirectoryFlag; + __u16 ByteCount; /* bct = 0 */ + } OPEN_RSP; + typedef struct { + struct_group_attr(common_attributes,, + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 Attributes; + ); + __u32 Pad1; + __le64 AllocationSize; + __le64 EndOfFile; + __le32 NumberOfLinks; + __u8 DeletePending; + __u8 Directory; + __u16 Pad2; + __le32 EASize; + __le32 FileNameLength; + union { + char __pad; + DECLARE_FLEX_ARRAY(char, FileName); + }; + } FILE_ALL_INFO; /* level 0x107 QPathInfo */ + """ + expected = """ + typedef struct smb_com_open_rsp { + struct smb_hdr hdr; + __u8 AndXCommand; + __u8 AndXReserved; + __le16 AndXOffset; + __u8 OplockLevel; + __u16 Fid; + __le32 CreateAction; + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 FileAttributes; + __le64 AllocationSize; + __le64 EndOfFile; + __le16 FileType; + __le16 DeviceState; + __u8 DirectoryFlag; + __u16 ByteCount; + } OPEN_RSP; + typedef struct { + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 Attributes; + __u32 Pad1; + __le64 AllocationSize; + __le64 EndOfFile; + __le32 NumberOfLinks; + __u8 DeletePending; + __u8 Directory; + __u16 Pad2; + __le32 EASize; + __le32 FileNameLength; + union { + char __pad; + char FileName[]; + }; + } FILE_ALL_INFO; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_raw_struct_group(self): + """ + Test a __struct_group pattern from include/uapi/cxl/features.h. + """ + line = """ + struct cxl_mbox_get_sup_feats_out { + __struct_group(cxl_mbox_get_sup_feats_out_hdr, hdr, /* empty */, + __le16 num_entries; + __le16 supported_feats; + __u8 reserved[4]; + ); + struct cxl_feat_entry ents[] __counted_by_le(num_entries); + } __attribute__ ((__packed__)); + """ + expected = """ + struct cxl_mbox_get_sup_feats_out { + __le16 num_entries; + __le16 supported_feats; + __u8 reserved[4]; + struct cxl_feat_entry ents[]; + }; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_raw_struct_group_tagged(self): + r""" + Test cxl_regs with struct_group_tagged patterns from drivers/cxl/cxl.h. + + NOTE: + + This one has actually a violation from what kernel-doc would + expect: Kernel-doc regex expects only 3 members, but this is + actually defined as:: + + #define struct_group_tagged(TAG, NAME, MEMBERS...) + + The replace expression there is:: + + struct \1 { \3 } \2; + + but it should be really something like:: + + struct \1 { \3 \4 \5 \6 \7 \8 ... } \2; + + a later fix would be needed to address it. + + """ + line = """ + struct cxl_regs { + struct_group_tagged(cxl_component_regs, component, + void __iomem *hdm_decoder; + void __iomem *ras; + ); + + + /* This is actually a violation: too much commas */ + struct_group_tagged(cxl_device_regs, device_regs, + void __iomem *status, *mbox, *memdev; + ); + + struct_group_tagged(cxl_pmu_regs, pmu_regs, + void __iomem *pmu; + ); + + struct_group_tagged(cxl_rch_regs, rch_regs, + void __iomem *dport_aer; + ); + + struct_group_tagged(cxl_rcd_regs, rcd_regs, + void __iomem *rcd_pcie_cap; + ); + }; + """ + expected = """ + struct cxl_regs { + struct cxl_component_regs { + void __iomem *hdm_decoder; + void __iomem *ras; + } component; + + struct cxl_device_regs { + void __iomem *status, *mbox, *memdev; + } device_regs; + + struct cxl_pmu_regs { + void __iomem *pmu; + } pmu_regs; + + struct cxl_rch_regs { + void __iomem *dport_aer; + } rch_regs; + + struct cxl_rcd_regs { + void __iomem *rcd_pcie_cap; + } rcd_regs; + }; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_struct_group_tagged_with_private(self): + """ + Replace struct_group_tagged with private, using the same regex + for the replacement as what happens in xforms_lists.py. + + As the private removal happens outside NestedGroup class, we manually + dropped the remaining part of the struct, to simulate what happens + at kdoc_parser. + + Taken from include/net/page_pool/types.h + """ + line = """ + struct page_pool_params { + struct_group_tagged(page_pool_params_slow, slow, + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + /* private: only under "slow" struct */ + unsigned int ignored; + ); + /* Struct below shall not be ignored */ + struct_group_tagged(page_pool_params_fast, fast, + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + ); + }; + """ + expected = """ + struct page_pool_params { + struct page_pool_params_slow { + struct net_device *netdev; + unsigned int queue_idx; + unsigned int flags; + } slow; + struct page_pool_params_fast { + unsigned int order; + unsigned int pool_size; + int nid; + struct device *dev; + struct napi_struct *napi; + enum dma_data_direction dma_dir; + unsigned int max_len; + unsigned int offset; + } fast; + }; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_struct_kcov(self): + """ + """ + line = """ + struct kcov { + refcount_t refcount; + spinlock_t lock; + enum kcov_mode mode __guarded_by(&lock); + unsigned int size __guarded_by(&lock); + void *area __guarded_by(&lock); + struct task_struct *t __guarded_by(&lock); + bool remote; + unsigned int remote_size; + int sequence; + }; + """ + expected = """ + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + + def test_struct_kcov(self): + """ + Test a struct from kernel/kcov.c. + """ + line = """ + struct kcov { + refcount_t refcount; + spinlock_t lock; + enum kcov_mode mode __guarded_by(&lock); + unsigned int size __guarded_by(&lock); + void *area __guarded_by(&lock); + struct task_struct *t __guarded_by(&lock); + bool remote; + unsigned int remote_size; + int sequence; + }; + """ + expected = """ + struct kcov { + refcount_t refcount; + spinlock_t lock; + enum kcov_mode mode; + unsigned int size; + void *area; + struct task_struct *t; + bool remote; + unsigned int remote_size; + int sequence; + }; + """ + + result = self.apply_transforms("struct", line) + self.assertLogicallyEqual(result, expected) + + def test_vars_stackdepot(self): + """ + Test guarded_by on vars from lib/stackdepot.c. + """ + line = """ + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); + void **stack_pools __pt_guarded_by(&pool_lock); + """ + expected = """ + size_t pool_offset = DEPOT_POOL_SIZE; + struct list_head free_stacks; + void **stack_pools; + """ + + result = self.apply_transforms("var", line) + self.assertLogicallyEqual(result, expected) + + def test_functions_with_acquires_and_releases(self): + """ + Test guarded_by on vars from lib/stackdepot.c. + """ + line = """ + bool prepare_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info) \ + __cond_acquires(true, &report_lock); + + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) \ + __cond_acquires(0, RCU_BH); + + bool undo_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info) \ + __cond_releases(true, &report_lock); + + void debugfs_enter_cancellation(struct file *file, + struct debugfs_cancellation *c) \ + __acquires(cancellation); + + void debugfs_leave_cancellation(struct file *file, + struct debugfs_cancellation *c) \ + __releases(cancellation); + + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) \ + __acquires(lockp); + + void acpi_os_release_lock(acpi_spinlock lockp, + acpi_cpu_flags not_used) \ + __releases(lockp) + """ + expected = """ + bool prepare_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info); + + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c); + + bool undo_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info); + + void debugfs_enter_cancellation(struct file *file, + struct debugfs_cancellation *c); + + void debugfs_leave_cancellation(struct file *file, + struct debugfs_cancellation *c); + + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp); + + void acpi_os_release_lock(acpi_spinlock lockp, + acpi_cpu_flags not_used) + """ + + result = self.apply_transforms("func", line) + self.assertLogicallyEqual(result, expected) + # # Run all tests # From 600079fdcf46fafe15b4ccd62804d66e05309cc6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:34 +0100 Subject: [PATCH 091/162] docs: kdoc: replace NestedMatch with CMatch Our previous approach to solve nested structs were to use NestedMatch. It works well, but adding support to parse delimiters is very complex. Instead, use CMatch, which uses a C tokenizer, making the code more reliable and simpler. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <900bff66f8093402999f9fe055fbfa3fa33a8d8b.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 2 +- tools/lib/python/kdoc/xforms_lists.py | 31 ++++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 62d8030cf532..efd58c88ff31 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -14,7 +14,7 @@ import re from pprint import pformat from kdoc.c_lex import CTokenizer -from kdoc.kdoc_re import NestedMatch, KernRe +from kdoc.kdoc_re import KernRe from kdoc.kdoc_item import KdocItem # diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index c07cbe1e6349..7fa7f52cec7b 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -4,7 +4,8 @@ import re -from kdoc.kdoc_re import KernRe, NestedMatch +from kdoc.kdoc_re import KernRe +from kdoc.c_lex import CMatch struct_args_pattern = r'([^,)]+)' @@ -60,7 +61,7 @@ class CTransforms: # # As it doesn't properly match the end parenthesis on some cases. # - # So, a better solution was crafted: there's now a NestedMatch + # So, a better solution was crafted: there's now a CMatch # class that ensures that delimiters after a search are properly # matched. So, the implementation to drop STRUCT_GROUP() will be # handled in separate. @@ -72,9 +73,9 @@ class CTransforms: # # Replace macros # - # TODO: use NestedMatch for FOO($1, $2, ...) matches + # TODO: use CMatch for FOO($1, $2, ...) matches # - # it is better to also move those to the NestedMatch logic, + # it is better to also move those to the CMatch logic, # to ensure that parentheses will be properly matched. # (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), @@ -95,17 +96,17 @@ class CTransforms: (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), - (NestedMatch(r"__cond_acquires\s*\("), ""), - (NestedMatch(r"__cond_releases\s*\("), ""), - (NestedMatch(r"__acquires\s*\("), ""), - (NestedMatch(r"__releases\s*\("), ""), - (NestedMatch(r"__must_hold\s*\("), ""), - (NestedMatch(r"__must_not_hold\s*\("), ""), - (NestedMatch(r"__must_hold_shared\s*\("), ""), - (NestedMatch(r"__cond_acquires_shared\s*\("), ""), - (NestedMatch(r"__acquires_shared\s*\("), ""), - (NestedMatch(r"__releases_shared\s*\("), ""), - (NestedMatch(r'\bSTRUCT_GROUP\('), r'\0'), + (CMatch(r"__cond_acquires"), ""), + (CMatch(r"__cond_releases"), ""), + (CMatch(r"__acquires"), ""), + (CMatch(r"__releases"), ""), + (CMatch(r"__must_hold"), ""), + (CMatch(r"__must_not_hold"), ""), + (CMatch(r"__must_hold_shared"), ""), + (CMatch(r"__cond_acquires_shared"), ""), + (CMatch(r"__acquires_shared"), ""), + (CMatch(r"__releases_shared"), ""), + (CMatch(r"STRUCT_GROUP"), r'\0'), ] #: Transforms for function prototypes. From ae63a5b9203bcb3dce4819c07409b27734180eea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:35 +0100 Subject: [PATCH 092/162] docs: kdoc_re: get rid of NestedMatch class Now that everything was converted to CMatch, we can get rid of the previous NestedMatch implementation. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_re.py | 201 ------------------------------- 1 file changed, 201 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 085b89a4547c..6f3ae28859ea 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -140,204 +140,3 @@ class KernRe: """ return self.last_match.groups() - -#: Nested delimited pairs (brackets and parenthesis) -DELIMITER_PAIRS = { - '{': '}', - '(': ')', - '[': ']', -} - -#: compiled delimiters -RE_DELIM = KernRe(r'[\{\}\[\]\(\)]') - - -class NestedMatch: - """ - Finding nested delimiters is hard with regular expressions. It is - even harder on Python with its normal re module, as there are several - advanced regular expressions that are missing. - - This is the case of this pattern:: - - '\\bSTRUCT_GROUP(\\(((?:(?>[^)(]+)|(?1))*)\\))[^;]*;' - - which is used to properly match open/close parentheses of the - string search STRUCT_GROUP(), - - Add a class that counts pairs of delimiters, using it to match and - replace nested expressions. - - The original approach was suggested by: - - https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex - - Although I re-implemented it to make it more generic and match 3 types - of delimiters. The logic checks if delimiters are paired. If not, it - will ignore the search string. - """ - - # TODO: make NestedMatch handle multiple match groups - # - # Right now, regular expressions to match it are defined only up to - # the start delimiter, e.g.: - # - # \bSTRUCT_GROUP\( - # - # is similar to: STRUCT_GROUP\((.*)\) - # except that the content inside the match group is delimiter-aligned. - # - # The content inside parentheses is converted into a single replace - # group (e.g. r`\0'). - # - # It would be nice to change such definition to support multiple - # match groups, allowing a regex equivalent to: - # - # FOO\((.*), (.*), (.*)\) - # - # it is probably easier to define it not as a regular expression, but - # with some lexical definition like: - # - # FOO(arg1, arg2, arg3) - - def __init__(self, regex): - self.regex = KernRe(regex) - - def _search(self, line): - """ - Finds paired blocks for a regex that ends with a delimiter. - - The suggestion of using finditer to match pairs came from: - https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex - but I ended using a different implementation to align all three types - of delimiters and seek for an initial regular expression. - - The algorithm seeks for open/close paired delimiters and places them - into a stack, yielding a start/stop position of each match when the - stack is zeroed. - - The algorithm should work fine for properly paired lines, but will - silently ignore end delimiters that precede a start delimiter. - This should be OK for kernel-doc parser, as unaligned delimiters - would cause compilation errors. So, we don't need to raise exceptions - to cover such issues. - """ - - stack = [] - - for match_re in self.regex.finditer(line): - start = match_re.start() - offset = match_re.end() - string_char = None - escape = False - - d = line[offset - 1] - if d not in DELIMITER_PAIRS: - continue - - end = DELIMITER_PAIRS[d] - stack.append(end) - - for match in RE_DELIM.finditer(line[offset:]): - pos = match.start() + offset - - d = line[pos] - - if escape: - escape = False - continue - - if string_char: - if d == '\\': - escape = True - elif d == string_char: - string_char = None - - continue - - if d in ('"', "'"): - string_char = d - continue - - if d in DELIMITER_PAIRS: - end = DELIMITER_PAIRS[d] - - stack.append(end) - continue - - # Does the end delimiter match what is expected? - if stack and d == stack[-1]: - stack.pop() - - if not stack: - yield start, offset, pos + 1 - break - - def search(self, line): - """ - This is similar to re.search: - - It matches a regex that it is followed by a delimiter, - returning occurrences only if all delimiters are paired. - """ - - for t in self._search(line): - - yield line[t[0]:t[2]] - - def sub(self, sub, line, count=0): - """ - This is similar to re.sub: - - It matches a regex that it is followed by a delimiter, - replacing occurrences only if all delimiters are paired. - - if the sub argument contains:: - - r'\0' - - it will work just like re: it places there the matched paired data - with the delimiter stripped. - - If count is different than zero, it will replace at most count - items. - """ - out = "" - - cur_pos = 0 - n = 0 - - for start, end, pos in self._search(line): - out += line[cur_pos:start] - - # Value, ignoring start/end delimiters - value = line[end:pos - 1] - - # replaces \0 at the sub string, if \0 is used there - new_sub = sub - new_sub = new_sub.replace(r'\0', value) - - out += new_sub - - # Drop end ';' if any - if pos < len(line) and line[pos] == ';': - pos += 1 - - cur_pos = pos - n += 1 - - if count and count >= n: - break - - # Append the remaining string - l = len(line) - out += line[cur_pos:l] - - return out - - def __repr__(self): - """ - Returns a displayable version of the class init. - """ - - return f'NestedMatch("{self.regex.regex.pattern}")' From f63e6163c7e4f988b2ff35721ffc86b95425293f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:36 +0100 Subject: [PATCH 093/162] docs: xforms_lists: handle struct_group directly The previous logic was handling struct_group on two steps. Remove the previous approach, as CMatch can do it the right way on a single step. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/xforms_lists.py | 53 +++------------------------ 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index 7fa7f52cec7b..98632c50a146 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -32,52 +32,6 @@ class CTransforms: (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), (KernRe(r'\s*____cacheline_aligned', re.S), ' '), (KernRe(r'\s*__cacheline_group_(begin|end)\([^\)]+\);'), ''), - # - # Unwrap struct_group macros based on this definition: - # __struct_group(TAG, NAME, ATTRS, MEMBERS...) - # which has variants like: struct_group(NAME, MEMBERS...) - # Only MEMBERS arguments require documentation. - # - # Parsing them happens on two steps: - # - # 1. drop struct group arguments that aren't at MEMBERS, - # storing them as STRUCT_GROUP(MEMBERS) - # - # 2. remove STRUCT_GROUP() ancillary macro. - # - # The original logic used to remove STRUCT_GROUP() using an - # advanced regex: - # - # \bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*; - # - # with two patterns that are incompatible with - # Python re module, as it has: - # - # - a recursive pattern: (?1) - # - an atomic grouping: (?>...) - # - # I tried a simpler version: but it didn't work either: - # \bSTRUCT_GROUP\(([^\)]+)\)[^;]*; - # - # As it doesn't properly match the end parenthesis on some cases. - # - # So, a better solution was crafted: there's now a CMatch - # class that ensures that delimiters after a search are properly - # matched. So, the implementation to drop STRUCT_GROUP() will be - # handled in separate. - # - (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('), - (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GROUP('), - (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'struct \1 \2; STRUCT_GROUP('), - (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP('), - # - # Replace macros - # - # TODO: use CMatch for FOO($1, $2, ...) matches - # - # it is better to also move those to the CMatch logic, - # to ensure that parentheses will be properly matched. - # (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), @@ -106,7 +60,12 @@ class CTransforms: (CMatch(r"__cond_acquires_shared"), ""), (CMatch(r"__acquires_shared"), ""), (CMatch(r"__releases_shared"), ""), - (CMatch(r"STRUCT_GROUP"), r'\0'), + + (CMatch('struct_group'), r'\2'), + (CMatch('struct_group_attr'), r'\3'), + (CMatch('struct_group_tagged'), r'struct \1 \2; \3'), + (CMatch('__struct_group'), r'\4'), + ] #: Transforms for function prototypes. From 2f07ddbd5793df4ec24f727322cc68065feb3568 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:37 +0100 Subject: [PATCH 094/162] docs: xforms_lists: better evaluate struct_group macros The previous approach were to unwind nested structs/unions. Now that we have a logic that can handle it well, use it to ensure that struct_group macros will properly reflect the actual struct. Note that the replacemend logic still simplifies the code a little bit, as the basic build block for struct group is: union { \ struct { MEMBERS } ATTRS; \ struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \ } ATTRS There: - ATTRS is meant to add extra macro attributes like __packed which we already discard, as they aren't relevant to document struct members; - TAG is used only when built with __cplusplus. So, instead, convert them into just: struct { MEMBERS }; Please notice that here, we're using the greedy version of the backrefs, as MEMBERS is actually MEMBERS... on all such macros. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <24bf2c036b08814d9b4aabc27542fd3b2ff54424.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/xforms_lists.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index 98632c50a146..2056572852fd 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -61,10 +61,16 @@ class CTransforms: (CMatch(r"__acquires_shared"), ""), (CMatch(r"__releases_shared"), ""), - (CMatch('struct_group'), r'\2'), - (CMatch('struct_group_attr'), r'\3'), - (CMatch('struct_group_tagged'), r'struct \1 \2; \3'), - (CMatch('__struct_group'), r'\4'), + # + # Macro __struct_group() creates an union with an anonymous + # and a non-anonymous struct, depending on the parameters. We only + # need one of those at kernel-doc, as we won't be documenting the same + # members twice. + # + (CMatch('struct_group'), r'struct { \2+ };'), + (CMatch('struct_group_attr'), r'struct { \3+ };'), + (CMatch('struct_group_tagged'), r'struct { \3+ };'), + (CMatch('__struct_group'), r'struct { \4+ };'), ] From 024e200e2a89d71dceff7d1bff8ae77b145726e0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:38 +0100 Subject: [PATCH 095/162] docs: c_lex: setup a logger to report tokenizer issues Report file that has issues detected via CMatch and CTokenizer. This is done by setting up a logger that will be overriden by kdoc_parser, when used on it. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Aleksandr Loktionov Signed-off-by: Jonathan Corbet Message-ID: <903ad83ae176196a50444e66177a4f5bcdef5199.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/c_lex.py | 16 ++++++++++++++++ tools/lib/python/kdoc/kdoc_parser.py | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py index 20e50ff0ecd5..b6d58bd470a9 100644 --- a/tools/lib/python/kdoc/c_lex.py +++ b/tools/lib/python/kdoc/c_lex.py @@ -22,6 +22,22 @@ from .kdoc_re import KernRe log = logging.getLogger(__name__) +def tokenizer_set_log(logger, prefix = ""): + """ + Replace the module‑level logger with a LoggerAdapter that + prepends *prefix* to every message. + """ + global log + + class PrefixAdapter(logging.LoggerAdapter): + """ + Ancillary class to set prefix on all message logs. + """ + def process(self, msg, kwargs): + return f"{prefix}{msg}", kwargs + + # Wrap the provided logger in our adapter + log = PrefixAdapter(logger, {"prefix": prefix}) class CToken(): """ diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index efd58c88ff31..f90c6dd0343d 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -13,7 +13,7 @@ import sys import re from pprint import pformat -from kdoc.c_lex import CTokenizer +from kdoc.c_lex import CTokenizer, tokenizer_set_log from kdoc.kdoc_re import KernRe from kdoc.kdoc_item import KdocItem @@ -253,6 +253,8 @@ class KernelDoc: self.config = config self.xforms = xforms + tokenizer_set_log(self.config.log, f"{self.fname}: CMatch: ") + # Initial state for the state machines self.state = state.NORMAL From 827b9458c9334733c598ff755bea84774ca97564 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:39 +0100 Subject: [PATCH 096/162] docs: kernel-doc.rst: document private: scope propagation This was an undefined behavior, but at least one place used private: inside a nested struct meant to not be propagated outside it. Kernel-doc now defines how this is propagated. So, document that. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- Documentation/doc-guide/kernel-doc.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/doc-guide/kernel-doc.rst b/Documentation/doc-guide/kernel-doc.rst index 8d2c09fb36e4..1c148fe8e1f9 100644 --- a/Documentation/doc-guide/kernel-doc.rst +++ b/Documentation/doc-guide/kernel-doc.rst @@ -213,6 +213,10 @@ The ``private:`` and ``public:`` tags must begin immediately following a ``/*`` comment marker. They may optionally include comments between the ``:`` and the ending ``*/`` marker. +When ``private:`` is used on nested structs, it propagates only to inner +structs/unions. + + Example:: /** @@ -256,8 +260,10 @@ It is possible to document nested structs and unions, like:: union { struct { int memb1; + /* private: hides memb2 from documentation */ int memb2; }; + /* Everything here is public again, as private scope finished */ struct { void *memb3; int memb4; From 12aa7753ff4c5fea405d139bcf67f49bda2c932e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:40 +0100 Subject: [PATCH 097/162] docs: kdoc: ensure that comments are dropped before calling split_struct_proto() Changeset 2b957decdb6c ("docs: kdoc: don't add broken comments inside prototypes") revealed a hidden bug at split_struct_proto(): some comments there may break its capability of properly identifying a struct. Fixing it is as simple as stripping comments before calling it. Fixes: 2b957decdb6c ("docs: kdoc: don't add broken comments inside prototypes") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_parser.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index f90c6dd0343d..8b2c9d0f0c58 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -723,6 +723,7 @@ class KernelDoc: # # Do the basic parse to get the pieces of the declaration. # + proto = trim_private_members(proto) struct_parts = self.split_struct_proto(proto) if not struct_parts: self.emit_msg(ln, f"{proto} error: Cannot parse struct or union!") @@ -763,6 +764,7 @@ class KernelDoc: # Strip preprocessor directives. Note that this depends on the # trailing semicolon we added in process_proto_type(). # + proto = trim_private_members(proto) proto = KernRe(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags=re.S).sub('', proto) # # Parse out the name and members of the enum. Typedef form first. @@ -770,7 +772,7 @@ class KernelDoc: r = KernRe(r'typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;') if r.search(proto): declaration_name = r.group(2) - members = trim_private_members(r.group(1)) + members = r.group(1) # # Failing that, look for a straight enum # @@ -778,7 +780,7 @@ class KernelDoc: r = KernRe(r'enum\s+(\w*)\s*\{(.*)\}') if r.match(proto): declaration_name = r.group(1) - members = trim_private_members(r.group(2)) + members = r.group(2) # # OK, this isn't going to work. # From 79d881beb721d27f679f0dc1cba2d5fe2d7f6d8d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:41 +0100 Subject: [PATCH 098/162] docs: kdoc_parser: avoid tokenizing structs everytime Most of the rules inside CTransforms are of the type CMatch. Don't re-parse the source code every time. Doing this doesn't change the output, but makes kdoc almost as fast as before the tokenizer patches: # Before tokenizer patches $ time ./scripts/kernel-doc . -man >original 2>&1 real 0m42.933s user 0m36.523s sys 0m1.145s # After tokenizer patches $ time ./scripts/kernel-doc . -man >before 2>&1 real 1m29.853s user 1m23.974s sys 0m1.237s # After this patch $ time ./scripts/kernel-doc . -man >after 2>&1 real 0m48.579s user 0m45.938s sys 0m0.988s $ diff -s before after Files before and after are identical Manually checked the differences between original and after with: $ diff -U0 -prBw original after|grep -v Warning|grep -v "@@"|less They're due: - whitespace fixes; - struct_group are now better handled; - several badly-generated man pages from broken inline kernel-doc markups are now fixed. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <1cc2a4286ebf7d4b2d03fcaf42a1ba9fa09004b9.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_parser.py | 1 - tools/lib/python/kdoc/xforms_lists.py | 30 +++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 8b2c9d0f0c58..f6c4ee3b18c9 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -737,7 +737,6 @@ class KernelDoc: # # Go through the list of members applying all of our transformations. # - members = trim_private_members(members) members = self.xforms.apply("struct", members) # diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index 2056572852fd..5a62d4a450cb 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -5,7 +5,7 @@ import re from kdoc.kdoc_re import KernRe -from kdoc.c_lex import CMatch +from kdoc.c_lex import CMatch, CTokenizer struct_args_pattern = r'([^,)]+)' @@ -16,6 +16,12 @@ class CTransforms: into something we can parse and generate kdoc for. """ + # + # NOTE: + # Due to performance reasons, place CMatch rules before KernRe, + # as this avoids running the C parser every time. + # + #: Transforms for structs and unions. struct_xforms = [ # Strip attributes @@ -124,13 +130,25 @@ class CTransforms: "var": var_xforms, } - def apply(self, xforms_type, text): + def apply(self, xforms_type, source): """ - Apply a set of transforms to a block of text. + Apply a set of transforms to a block of source. + + As tokenizer is used here, this function also remove comments + at the end. """ if xforms_type not in self.xforms: - return text + return source + + if isinstance(source, str): + source = CTokenizer(source) for search, subst in self.xforms[xforms_type]: - text = search.sub(subst, text) - return text + # + # KernRe only accept strings. + # + if isinstance(search, KernRe): + source = str(source) + + source = search.sub(subst, source) + return str(source) From 7538df7a2d7d26428803cf8053476169a6d28659 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2026 19:09:42 +0100 Subject: [PATCH 099/162] docs: xforms_lists: use CMatch for all identifiers CMatch is lexically correct and replaces only identifiers, which is exactly where macro transformations happen. Use it to make the output safer and ensure that all arguments will be parsed the right way, even on complex cases. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <86d4a07ff0e054207747fabf38d6bb261b52b5fa.1773770483.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/xforms_lists.py | 159 +++++++++++++------------- 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py index 5a62d4a450cb..f6ea9efb11ae 100644 --- a/tools/lib/python/kdoc/xforms_lists.py +++ b/tools/lib/python/kdoc/xforms_lists.py @@ -7,7 +7,8 @@ import re from kdoc.kdoc_re import KernRe from kdoc.c_lex import CMatch, CTokenizer -struct_args_pattern = r'([^,)]+)' +struct_args_pattern = r"([^,)]+)" + class CTransforms: """ @@ -24,48 +25,40 @@ class CTransforms: #: Transforms for structs and unions. struct_xforms = [ - # Strip attributes - (KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=re.I | re.S, cache=False), ' '), - (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), - (KernRe(r'\s*__guarded_by\s*\([^\)]*\)', re.S), ' '), - (KernRe(r'\s*__pt_guarded_by\s*\([^\)]*\)', re.S), ' '), - (KernRe(r'\s*__packed\s*', re.S), ' '), - (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), - (KernRe(r'\s*__private', re.S), ' '), - (KernRe(r'\s*__rcu', re.S), ' '), - (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), - (KernRe(r'\s*____cacheline_aligned', re.S), ' '), - (KernRe(r'\s*__cacheline_group_(begin|end)\([^\)]+\);'), ''), - (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S), - r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), - (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), - r'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), - (KernRe(r'DECLARE_BITMAP\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', - re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), - (KernRe(r'DECLARE_HASHTABLE\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + r'\)', - re.S), r'unsigned long \1[1 << ((\2) - 1)]'), - (KernRe(r'DECLARE_KFIFO\s*\(' + struct_args_pattern + r',\s*' + struct_args_pattern + - r',\s*' + struct_args_pattern + r'\)', re.S), r'\2 *\1'), - (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + struct_args_pattern + r',\s*' + - struct_args_pattern + r'\)', re.S), r'\2 *\1'), - (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + struct_args_pattern + r',\s*' + - struct_args_pattern + r'\)', re.S), r'\1 \2[]'), - (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + struct_args_pattern + r'\)', re.S), r'dma_addr_t \1'), - (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + struct_args_pattern + r'\)', re.S), r'__u32 \1'), - (KernRe(r'VIRTIO_DECLARE_FEATURES\(([\w_]+)\)'), r'union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }'), - - (CMatch(r"__cond_acquires"), ""), - (CMatch(r"__cond_releases"), ""), - (CMatch(r"__acquires"), ""), - (CMatch(r"__releases"), ""), - (CMatch(r"__must_hold"), ""), - (CMatch(r"__must_not_hold"), ""), - (CMatch(r"__must_hold_shared"), ""), - (CMatch(r"__cond_acquires_shared"), ""), - (CMatch(r"__acquires_shared"), ""), - (CMatch(r"__releases_shared"), ""), + (CMatch("__attribute__"), ""), + (CMatch("__aligned"), ""), + (CMatch("__counted_by"), ""), + (CMatch("__counted_by_(le|be)"), ""), + (CMatch("__guarded_by"), ""), + (CMatch("__pt_guarded_by"), ""), + (CMatch("__packed"), ""), + (CMatch("CRYPTO_MINALIGN_ATTR"), ""), + (CMatch("__private"), ""), + (CMatch("__rcu"), ""), + (CMatch("____cacheline_aligned_in_smp"), ""), + (CMatch("____cacheline_aligned"), ""), + (CMatch("__cacheline_group_(?:begin|end)"), ""), + (CMatch("__ETHTOOL_DECLARE_LINK_MODE_MASK"), r"DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)"), + (CMatch("DECLARE_PHY_INTERFACE_MASK",),r"DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)"), + (CMatch("DECLARE_BITMAP"), r"unsigned long \1[BITS_TO_LONGS(\2)]"), + (CMatch("DECLARE_HASHTABLE"), r"unsigned long \1[1 << ((\2) - 1)]"), + (CMatch("DECLARE_KFIFO"), r"\2 *\1"), + (CMatch("DECLARE_KFIFO_PTR"), r"\2 *\1"), + (CMatch("(?:__)?DECLARE_FLEX_ARRAY"), r"\1 \2[]"), + (CMatch("DEFINE_DMA_UNMAP_ADDR"), r"dma_addr_t \1"), + (CMatch("DEFINE_DMA_UNMAP_LEN"), r"__u32 \1"), + (CMatch("VIRTIO_DECLARE_FEATURES"), r"union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }"), + (CMatch("__cond_acquires"), ""), + (CMatch("__cond_releases"), ""), + (CMatch("__acquires"), ""), + (CMatch("__releases"), ""), + (CMatch("__must_hold"), ""), + (CMatch("__must_not_hold"), ""), + (CMatch("__must_hold_shared"), ""), + (CMatch("__cond_acquires_shared"), ""), + (CMatch("__acquires_shared"), ""), + (CMatch("__releases_shared"), ""), + (CMatch("__attribute__"), ""), # # Macro __struct_group() creates an union with an anonymous @@ -73,51 +66,57 @@ class CTransforms: # need one of those at kernel-doc, as we won't be documenting the same # members twice. # - (CMatch('struct_group'), r'struct { \2+ };'), - (CMatch('struct_group_attr'), r'struct { \3+ };'), - (CMatch('struct_group_tagged'), r'struct { \3+ };'), - (CMatch('__struct_group'), r'struct { \4+ };'), - + (CMatch("struct_group"), r"struct { \2+ };"), + (CMatch("struct_group_attr"), r"struct { \3+ };"), + (CMatch("struct_group_tagged"), r"struct { \3+ };"), + (CMatch("__struct_group"), r"struct { \4+ };"), ] #: Transforms for function prototypes. function_xforms = [ - (KernRe(r"^static +"), ""), - (KernRe(r"^extern +"), ""), - (KernRe(r"^asmlinkage +"), ""), - (KernRe(r"^inline +"), ""), - (KernRe(r"^__inline__ +"), ""), - (KernRe(r"^__inline +"), ""), - (KernRe(r"^__always_inline +"), ""), - (KernRe(r"^noinline +"), ""), - (KernRe(r"^__FORTIFY_INLINE +"), ""), - (KernRe(r"__init +"), ""), - (KernRe(r"__init_or_module +"), ""), - (KernRe(r"__exit +"), ""), - (KernRe(r"__deprecated +"), ""), - (KernRe(r"__flatten +"), ""), - (KernRe(r"__meminit +"), ""), - (KernRe(r"__must_check +"), ""), - (KernRe(r"__weak +"), ""), - (KernRe(r"__sched +"), ""), - (KernRe(r"_noprof"), ""), - (KernRe(r"__always_unused *"), ""), - (KernRe(r"__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +"), ""), - (KernRe(r"__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +"), ""), - (KernRe(r"__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +"), ""), - (KernRe(r"DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)"), r"\1, \2"), - (KernRe(r"__no_context_analysis\s*"), ""), - (KernRe(r"__attribute_const__ +"), ""), - (KernRe(r"__attribute__\s*\(\((?:[\w\s]+(?:\([^)]*\))?\s*,?)+\)\)\s+"), ""), + (CMatch("static"), ""), + (CMatch("extern"), ""), + (CMatch("asmlinkage"), ""), + (CMatch("inline"), ""), + (CMatch("__inline__"), ""), + (CMatch("__inline"), ""), + (CMatch("__always_inline"), ""), + (CMatch("noinline"), ""), + (CMatch("__FORTIFY_INLINE"), ""), + (CMatch("__init"), ""), + (CMatch("__init_or_module"), ""), + (CMatch("__exit"), ""), + (CMatch("__deprecated"), ""), + (CMatch("__flatten"), ""), + (CMatch("__meminit"), ""), + (CMatch("__must_check"), ""), + (CMatch("__weak"), ""), + (CMatch("__sched"), ""), + (CMatch("__always_unused"), ""), + (CMatch("__printf"), ""), + (CMatch("__(?:re)?alloc_size"), ""), + (CMatch("__diagnose_as"), ""), + (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), + (CMatch("__no_context_analysis"), ""), + (CMatch("__attribute_const__"), ""), + (CMatch("__attribute__"), ""), + + # + # HACK: this is similar to process_export() hack. It is meant to + # drop _noproof from function name. See for instance: + # ahash_request_alloc kernel-doc declaration at include/crypto/hash.h. + # + (KernRe("_noprof"), ""), ] #: Transforms for variable prototypes. var_xforms = [ - (KernRe(r"__read_mostly"), ""), - (KernRe(r"__ro_after_init"), ""), - (KernRe(r'\s*__guarded_by\s*\([^\)]*\)', re.S), ""), - (KernRe(r'\s*__pt_guarded_by\s*\([^\)]*\)', re.S), ""), - (KernRe(r"LIST_HEAD\(([\w_]+)\)"), r"struct list_head \1"), + (CMatch("__read_mostly"), ""), + (CMatch("__ro_after_init"), ""), + (CMatch("__guarded_by"), ""), + (CMatch("__pt_guarded_by"), ""), + (CMatch("LIST_HEAD"), r"struct list_head \1"), + (KernRe(r"(?://.*)$"), ""), (KernRe(r"(?:/\*.*\*/)"), ""), (KernRe(r";$"), ""), From 14b7775ef7471fbb9380048aabb3e96faa1e9123 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:01 +0100 Subject: [PATCH 100/162] unittests: test_tokenizer: better handle mismatch error The current logic is too sensitive to how c_lex name is placed. Also, it doesn't really check the log. Change it to check if the expected message will be reported after a call to C tokenizer with an invalid source. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <6e19578bc1ffa96e536dc31997ff658017f60173.1773823995.git.mchehab+huawei@kernel.org> --- tools/unittests/test_tokenizer.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/unittests/test_tokenizer.py b/tools/unittests/test_tokenizer.py index 5634b4a7283e..d1f3c565b9cf 100755 --- a/tools/unittests/test_tokenizer.py +++ b/tools/unittests/test_tokenizer.py @@ -46,10 +46,17 @@ def make_tokenizer_test(name, data): # # Check if logger is working # - if "log_level" in data: - with self.assertLogs('kdoc.c_lex', level='ERROR') as cm: + if "log_msg" in data: + with self.assertLogs() as cm: tokenizer = CTokenizer(data["source"]) + msg_found = False + for result in cm.output: + if data["log_msg"] in result: + msg_found = True + + self.assertTrue(msg_found, f"Missing log {data['log_msg']}") + return # @@ -124,7 +131,7 @@ TESTS_TOKENIZER = { "mismatch_error": { "source": "int a$ = 5;", # $ is illegal - "log_level": "ERROR", + "log_msg": "Unexpected token", }, } From b2d231f4a77800661b3fb812d997841a548c6526 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:02 +0100 Subject: [PATCH 101/162] docs: kdoc_re: better represent long regular expressions The Sphinx output from autodoc doesn't automatically break long lines, except on spaces. Change KernRe __repr__() to break the pattern on multiple strings, each one with a maximum limit of 60 characters. With that, documentation output for KernRe should now be displayable, even on long strings. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <60c264a9d277fed655b1a62df2195562c8596090.1773823995.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_re.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_re.py b/tools/lib/python/kdoc/kdoc_re.py index 6f3ae28859ea..28292efe25a2 100644 --- a/tools/lib/python/kdoc/kdoc_re.py +++ b/tools/lib/python/kdoc/kdoc_re.py @@ -70,10 +70,15 @@ class KernRe: flags_name = " | ".join(flags) + max_len = 60 + pattern = "" + for pos in range(0, len(self.regex.pattern), max_len): + pattern += '"' + self.regex.pattern[pos:max_len + pos] + '" ' + if flags_name: - return f'KernRe("{self.regex.pattern}", {flags_name})' + return f'KernRe({pattern}, {flags_name})' else: - return f'KernRe("{self.regex.pattern}")' + return f'KernRe({pattern})' def __add__(self, other): """ From 8c0b7c0d3c0e640b3ebb7f1f648ea322e56c227a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:03 +0100 Subject: [PATCH 102/162] docs: kdoc: add c_lex to generated documentation Do some fixes at groups() description for it to be parsed by Sphinx and add it to the documentation. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <799178cf30dd4022fdb1d029ba998a458e037b52.1773823995.git.mchehab+huawei@kernel.org> --- Documentation/tools/kdoc_ancillary.rst | 9 +++++++++ tools/lib/python/kdoc/c_lex.py | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Documentation/tools/kdoc_ancillary.rst b/Documentation/tools/kdoc_ancillary.rst index 3950d0a3f104..85f3806a431a 100644 --- a/Documentation/tools/kdoc_ancillary.rst +++ b/Documentation/tools/kdoc_ancillary.rst @@ -21,6 +21,15 @@ Regular expression class handler :undoc-members: +C tokenizer +=========== + +.. automodule:: lib.python.kdoc.c_lex + :members: + :show-inheritance: + :undoc-members: + + Chinese, Japanese and Korean variable fonts handler =================================================== diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py index b6d58bd470a9..e01b154f458e 100644 --- a/tools/lib/python/kdoc/c_lex.py +++ b/tools/lib/python/kdoc/c_lex.py @@ -336,13 +336,14 @@ class CTokenArgs: self.sub_tokeninzer = CTokenizer(sub_str) def groups(self, new_tokenizer): - """ + r""" Create replacement arguments for backrefs like: - ``\0``, ``\1``, ``\2``, ...``\n`` + ``\0``, ``\1``, ``\2``, ... ``\{number}`` - It also accepts a ``+`` character to the highest backref. When used, - it means in practice to ignore delimins after it, being greedy. + It also accepts a ``+`` character to the highest backref, like + ``\4+``. When used, the backref will be greedy, picking all other + arguments afterwards. The logic is smart enough to only go up to the maximum required argument, even if there are more. From e0ebee442d56c11df023b7c2d32edc3b0765b2f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:04 +0100 Subject: [PATCH 103/162] docs: kdoc_files: use a class to group config parameters Instead of abusing argparse.Namespace, define a class to store configuration parameters and logger. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_files.py | 45 ++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 8c2059623949..1c5cb9e5f0e8 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -9,7 +9,6 @@ Classes for navigating through the files that kernel-doc needs to handle to generate documentation. """ -import argparse import logging import os import re @@ -87,6 +86,28 @@ class GlobSourceFiles: file_not_found_cb(fname) +class KdocConfig(): + """ + Stores all configuration attributes that kdoc_parser and kdoc_output + needs. + """ + def __init__(self, verbose=False, werror=False, wreturn=False, + wshort_desc=False, wcontents_before_sections=False, + logger=None): + + self.verbose = verbose + self.werror = werror + self.wreturn = wreturn + self.wshort_desc = wshort_desc + self.wcontents_before_sections = wcontents_before_sections + + if logger: + self.log = logger + else: + self.log = logging.getLogger(__file__) + + self.warning = self.log.warning + class KernelFiles(): """ Parse kernel-doc tags on multiple kernel source files. @@ -224,29 +245,25 @@ class KernelFiles(): if kdoc_werror: werror = kdoc_werror + if not logger: + logger = logging.getLogger("kernel-doc") + else: + logger = logger + # Some variables are global to the parser logic as a whole as they are # used to send control configuration to KernelDoc class. As such, # those variables are read-only inside the KernelDoc. - self.config = argparse.Namespace + self.config = KdocConfig(verbose, werror, wreturn, wshort_desc, + wcontents_before_sections, logger) - self.config.verbose = verbose - self.config.werror = werror - self.config.wreturn = wreturn - self.config.wshort_desc = wshort_desc - self.config.wcontents_before_sections = wcontents_before_sections + # Override log warning, as we want to count errors + self.config.warning = self.warning if xforms: self.xforms = xforms else: self.xforms = CTransforms() - if not logger: - self.config.log = logging.getLogger("kernel-doc") - else: - self.config.log = logger - - self.config.warning = self.warning - self.config.src_tree = os.environ.get("SRCTREE", None) # Initialize variables that are internal to KernelFiles From 9ab2ca3dd127194a55bd9789c031e800fd19c254 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:05 +0100 Subject: [PATCH 104/162] docs: kdoc_files: move output symbols logic to kdoc_output When writing unittests for kdoc_output, it became clear that the logic with handles a series of KdocItem symbols from a single file belons to kdoc_output, and not to kdoc_files. Move the code to it. While here, also ensure that self.config will be placed together with set.out_style. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <4ebc26e37a0b544c50d50b8077760f147fa6a535.1773823995.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_files.py | 18 ++---------------- tools/lib/python/kdoc/kdoc_output.py | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 1c5cb9e5f0e8..58f4ee08e226 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -269,6 +269,7 @@ class KernelFiles(): # Initialize variables that are internal to KernelFiles self.out_style = out_style + self.out_style.set_config(self.config) self.errors = 0 self.results = {} @@ -311,8 +312,6 @@ class KernelFiles(): returning kernel-doc markups on each interaction. """ - self.out_style.set_config(self.config) - if not filenames: filenames = sorted(self.results.keys()) @@ -336,25 +335,12 @@ class KernelFiles(): function_table, enable_lineno, no_doc_sections) - msg = "" if fname not in self.results: self.config.log.warning("No kernel-doc for file %s", fname) continue symbols = self.results[fname] - self.out_style.set_symbols(symbols) - - for arg in symbols: - m = self.out_msg(fname, arg.name, arg) - - if m is None: - ln = arg.get("ln", 0) - dtype = arg.get('type', "") - - self.config.log.warning("%s:%d Can't handle %s", - fname, ln, dtype) - else: - msg += m + msg = self.out_style.output_symbols(fname, symbols) if msg: yield fname, msg diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 08539dd92cbb..73d71cbeabb5 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -222,6 +222,27 @@ class OutputFormat: return None + def output_symbols(self, fname, symbols): + """ + Handles a set of KdocItem symbols. + """ + self.set_symbols(symbols) + + msg = "" + for arg in symbols: + m = self.msg(fname, arg.name, arg) + + if m is None: + ln = arg.get("ln", 0) + dtype = arg.get('type', "") + + self.config.log.warning("%s:%d Can't handle %s", + fname, ln, dtype) + else: + msg += m + + return msg + # Virtual methods to be overridden by inherited classes # At the base class, those do nothing. def set_symbols(self, symbols): From 01c41b99c66ff26a102edbc4f9dff9c74692723e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:06 +0100 Subject: [PATCH 105/162] docs: kdoc_item: fix initial value for parameterdesc_start_lines Ensure that parameterdesc_start_lines is a dict at init time, as this is how it will be set later on at the parser. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <1b4ea24dd4cd82e6711e9be80168684427d74c30.1773823995.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_item.py b/tools/lib/python/kdoc/kdoc_item.py index 2b8a93f79716..c0585cdbcbd1 100644 --- a/tools/lib/python/kdoc/kdoc_item.py +++ b/tools/lib/python/kdoc/kdoc_item.py @@ -22,7 +22,7 @@ class KdocItem: self.sections = {} self.sections_start_lines = {} self.parameterlist = [] - self.parameterdesc_start_lines = [] + self.parameterdesc_start_lines = {} self.parameterdescs = {} self.parametertypes = {} # From 99364ba7f8dca5c1c2d08fe37c5835b86be141f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:07 +0100 Subject: [PATCH 106/162] docs: kdoc_item: add support to generate a KdocItem from a dict When reading the contents on a KdocItem using YAML, the data will be imported into a dict. Add a method to create a new KdocItem from a dict to allow converting such input into a real KdocItem. While here, address an issue that, if the class is initialized with an internal parameter outside the 4 initial arguments, it would end being added inside other_stuff, which breaks initializing it from a dict. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_item.py | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_item.py b/tools/lib/python/kdoc/kdoc_item.py index c0585cdbcbd1..5f41790efacb 100644 --- a/tools/lib/python/kdoc/kdoc_item.py +++ b/tools/lib/python/kdoc/kdoc_item.py @@ -25,12 +25,31 @@ class KdocItem: self.parameterdesc_start_lines = {} self.parameterdescs = {} self.parametertypes = {} + + self.warnings = [] + # # Just save everything else into our own dict so that the output # side can grab it directly as before. As we move things into more # structured data, this will, hopefully, fade away. # - self.other_stuff = other_stuff + known_keys = { + 'declaration_start_line', + 'sections', + 'sections_start_lines', + 'parameterlist', + 'parameterdesc_start_lines', + 'parameterdescs', + 'parametertypes', + 'warnings', + } + + self.other_stuff = {} + for k, v in other_stuff.items(): + if k in known_keys: + setattr(self, k, v) # real attribute + else: + self.other_stuff[k] = v def get(self, key, default = None): """ @@ -41,6 +60,20 @@ class KdocItem: def __getitem__(self, key): return self.get(key) + @classmethod + def from_dict(cls, d): + """Create a KdocItem from a plain dict.""" + + cp = d.copy() + name = cp.pop('name', None) + fname = cp.pop('fname', None) + type = cp.pop('type', None) + start_line = cp.pop('start_line', 1) + other_stuff = cp.pop('other_stuff', {}) + + # Everything that’s left goes straight to __init__ + return cls(name, fname, type, start_line, **cp, **other_stuff) + # # Tracking of section and parameter information. # From e394855fcc897f73f23c364a3a596b54cc879e4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:08 +0100 Subject: [PATCH 107/162] docs: kdoc_item: fix a typo on sections_start_lines Currently, there are 15 occurrences of section?_start_lines, with 10 using the plural way. This is an issue, as, while kdoc_output works with KdocItem, the term doesn't match its init value. The variable sections_start_lines stores multiple sections, so placing it in plural is its correct way. So, ensure that, on all parts of kdoc, this will be referred as sections_start_lines. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_item.py | 2 +- tools/lib/python/kdoc/kdoc_output.py | 2 +- tools/lib/python/kdoc/kdoc_parser.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_item.py b/tools/lib/python/kdoc/kdoc_item.py index 5f41790efacb..fe08cac861c2 100644 --- a/tools/lib/python/kdoc/kdoc_item.py +++ b/tools/lib/python/kdoc/kdoc_item.py @@ -82,7 +82,7 @@ class KdocItem: Set sections and start lines. """ self.sections = sections - self.section_start_lines = start_lines + self.sections_start_lines = start_lines def set_params(self, names, descs, types, starts): """ diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 73d71cbeabb5..1b54117dbe19 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -389,7 +389,7 @@ class RestFormat(OutputFormat): else: self.data += f'{self.lineprefix}**{section}**\n\n' - self.print_lineno(args.section_start_lines.get(section, 0)) + self.print_lineno(args.sections_start_lines.get(section, 0)) self.output_highlight(text) self.data += "\n" self.data += "\n" diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index f6c4ee3b18c9..35658a7e72d5 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -140,7 +140,7 @@ class KernelEntry: self.parametertypes = {} self.parameterdesc_start_lines = {} - self.section_start_lines = {} + self.sections_start_lines = {} self.sections = {} self.anon_struct_union = False @@ -220,7 +220,7 @@ class KernelEntry: self.sections[name] += '\n' + contents else: self.sections[name] = contents - self.section_start_lines[name] = self.new_start_line + self.sections_start_lines[name] = self.new_start_line self.new_start_line = 0 # self.config.log.debug("Section: %s : %s", name, pformat(vars(self))) @@ -316,7 +316,7 @@ class KernelDoc: for section in ["Description", "Return"]: if section in sections and not sections[section].rstrip(): del sections[section] - item.set_sections(sections, self.entry.section_start_lines) + item.set_sections(sections, self.entry.sections_start_lines) item.set_params(self.entry.parameterlist, self.entry.parameterdescs, self.entry.parametertypes, self.entry.parameterdesc_start_lines) From a5dea56ebd35a3027628b73db0968788e99c8412 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:09 +0100 Subject: [PATCH 108/162] docs: unittests: add a parser to test kernel-doc parser logic Validating that kernel-doc is parsing data properly is tricky. Add an unittest skeleton that alllows passing a source code and check if the corresponding values of export_table and entries returned by the parser are properly filled. It works by mocking a file input with the contents of a source string, an comparing if: - exports set matches; - expected KernelItem entries match. Create a new TestSelfValidate meant to check if the logic inside KdocParser.run_test() does its job of checking for differences inside KdocItem. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <8d91bfabd69de7aa44a0f5080ccb01aa41957e6d.1773823995.git.mchehab+huawei@kernel.org> --- tools/unittests/test_kdoc_parser.py | 202 ++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100755 tools/unittests/test_kdoc_parser.py diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py new file mode 100755 index 000000000000..26f74666a000 --- /dev/null +++ b/tools/unittests/test_kdoc_parser.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . +# +# pylint: disable=C0200,C0413,W0102,R0914 + +""" +Unit tests for kernel-doc parser. +""" + +import os +import unittest +import re +import sys + +from textwrap import dedent +from unittest.mock import patch, MagicMock, mock_open + +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) + +from kdoc.kdoc_parser import KernelDoc +from kdoc.kdoc_item import KdocItem +from kdoc.xforms_lists import CTransforms +from unittest_helper import run_unittest + +#: Regex to help cleaning whitespaces +RE_WHITESPC = re.compile(r"\s++") + +def clean_whitespc(val, relax_whitespace=False): + """ + Cleanup whitespaces to avoid false positives. + + By default, strip only bein/end whitespaces, but, when relax_whitespace + is true, also replace multiple whitespaces in the middle. + """ + + if isinstance(val, str): + val = val.strip() + if relax_whitespace: + val = RE_WHITESPC.sub("", val) + elif isinstance(val, list): + val = [clean_whitespc(item, relax_whitespace) for item in val] + elif isinstance(val, dict): + val = {k: clean_whitespc(v, relax_whitespace) for k, v in val.items()} + return val + +# +# Helper class to help mocking with +# +class KdocParser(unittest.TestCase): + """ + Base class to run KernelDoc parser class + """ + + DEFAULT = vars(KdocItem("", "", "", 0)) + + def setUp(self): + self.maxDiff = None + self.config = MagicMock() + self.config.log = MagicMock() + self.config.log.debug = MagicMock() + self.xforms = CTransforms() + + + def run_test(self, source, __expected_list, exports={}, fname="test.c", + relax_whitespace=False): + """ + Stores expected values and patch the test to use source as + a "file" input. + """ + debug_level = int(os.getenv("VERBOSE", "0")) + source = dedent(source) + + # Ensure that default values will be there + expected_list = [] + for e in __expected_list: + new_e = self.DEFAULT.copy() + new_e["fname"] = fname + for key, value in e.items(): + new_e[key] = value + + expected_list.append(new_e) + + patcher = patch('builtins.open', + new_callable=mock_open, read_data=source) + + kernel_doc = KernelDoc(self.config, fname, self.xforms) + + with patcher: + export_table, entries = kernel_doc.parse_kdoc() + + self.assertEqual(export_table, exports) + self.assertEqual(len(entries), len(expected_list)) + + for i in range(0, len(entries)): + + entry = entries[i] + expected = expected_list[i] + self.assertNotEqual(expected, None) + self.assertNotEqual(expected, {}) + self.assertIsInstance(entry, KdocItem) + + d = vars(entry) + for key, value in expected.items(): + result = clean_whitespc(d[key], relax_whitespace) + value = clean_whitespc(value, relax_whitespace) + + if debug_level > 1: + sys.stderr.write(f"{key}: assert('{result}' == '{value}')\n") + + self.assertEqual(result, value, msg=f"at {key}") + + +# +# Selttest class +# +class TestSelfValidate(KdocParser): + """ + Tests to check if logic inside KdocParser.run_test() is working. + """ + + SOURCE = """ + /** + * function3: Exported function + * @arg1: @arg1 does nothing + * + * Does nothing + * + * return: + * always return 0. + */ + int function3(char *arg1) { return 0; }; + EXPORT_SYMBOL(function3); + """ + + EXPECTED = [{ + 'name': 'function3', + 'type': 'function', + 'declaration_start_line': 2, + + 'sections_start_lines': { + 'Description': 4, + 'Return': 7, + }, + 'sections': { + 'Description': 'Does nothing\n\n', + 'Return': '\nalways return 0.\n' + }, + 'other_stuff': { + 'func_macro': False, + 'functiontype': 'int', + 'purpose': 'Exported function', + 'typedef': False + }, + 'parameterdescs': {'arg1': '@arg1 does nothing\n'}, + 'parameterlist': ['arg1'], + 'parameterdesc_start_lines': {'arg1': 3}, + 'parametertypes': {'arg1': 'char *arg1'}, + }] + + EXPORTS = {"function3"} + + def test_parse_pass(self): + """ + Test if export_symbol is properly handled. + """ + self.run_test(self.SOURCE, self.EXPECTED, self.EXPORTS) + + @unittest.expectedFailure + def test_no_exports(self): + """ + Test if export_symbol is properly handled. + """ + self.run_test(self.SOURCE, [], {}) + + @unittest.expectedFailure + def test_with_empty_expected(self): + """ + Test if export_symbol is properly handled. + """ + self.run_test(self.SOURCE, [], self.EXPORTS) + + @unittest.expectedFailure + def test_with_unfilled_expected(self): + """ + Test if export_symbol is properly handled. + """ + self.run_test(self.SOURCE, [{}], self.EXPORTS) + + @unittest.expectedFailure + def test_with_default_expected(self): + """ + Test if export_symbol is properly handled. + """ + self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS) + +# +# Run all tests +# +if __name__ == "__main__": + run_unittest(__file__) From f1cdbd824ca74e464a6159a0ae8af3ab1f123900 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:10 +0100 Subject: [PATCH 109/162] docs: add a schema to help creating unittests for kernel-doc Instead of hardcoding lots of tests inside a file, let's place them inside a yaml file. Add first a schema to handle it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/unittests/kdoc-test-schema.yaml | 156 ++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 tools/unittests/kdoc-test-schema.yaml diff --git a/tools/unittests/kdoc-test-schema.yaml b/tools/unittests/kdoc-test-schema.yaml new file mode 100644 index 000000000000..cf5079711cd8 --- /dev/null +++ b/tools/unittests/kdoc-test-schema.yaml @@ -0,0 +1,156 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . + +# KDoc Test File Schema + +# This schema contains objects and properties needed to run kernel-doc +# self-tests. + +$schema: "http://json-schema.org/draft-07/schema#" + +tests: + type: array + minItems: 1 + description: | + A list of kernel-doc tests. + + properties: + type: object + properties: + name: + type: string + description: | + Test name. Should be an unique identifier within the schema. + Don't prepend it with "test", as the dynamic test creation will + do it. + + description: + type: string + description: | + Test description + + source: + type: string + description: | + C source code that should be parsed by kernel-doc. + + fname: + type: string + description: | + The filename that contains the element. + When placing real testcases, please use here the name of + the C file (or header) from where the source code was picked. + + exports: + type: array + items: { type: string } + description: | + A list of export identifiers that are expected when parsing source. + + expected: + type: array + minItems: 1 + description: | + A list of expected values. This list consists on objects to check + both kdoc_parser and/or kdoc_output objects. + + items: + type: object + properties: + # + # kdoc_item + # + kdoc_item: + type: object + description: | + Object expected to represent the C source code after parsed + by tools/lib/python/kdoc/kdoc_parser.py KernelDoc class. + See tools/lib/python/kdoc/kdoc_item.py for its contents. + + properties: + name: + type: string + description: | + The name of the identifier (function name, struct name, etc). + type: + type: string + description: | + Type of the object, as filled by kdoc_parser. can be: + - enum + - typedef + - union + - struct + - var + - function + declaration_start_line: + type: integer + description: | + The line number where the kernel-doc markup started. + The first line of the code is line number 1. + sections: + type: object + additionalProperties: { type: string } + description: | + Sections inside the kernel-doc markups: + - "description" + - "return" + - any other part of the markup that starts with "something:" + sections_start_lines: + type: object + additionalProperties: { type: integer } + description: | + a list of section names and the starting line of it. + parameterlist: + type: array + items: { type: string } + description: | + Ordered list of parameter names. + + parameterdesc_start_lines: + type: object + additionalProperties: { type: integer } + description: | + Mapping from parameter name to the line where its + description starts. + parameterdescs: + type: object + additionalProperties: { type: string } + description: | + Mapping from parameter name to its description. + + parametertypes: + type: object + additionalProperties: { type: string } + description: | + Mapping from parameter name to its type. + + other_stuff: + type: object + additionalProperties: {} + description: | + Extra properties that will be stored at the item. + Should match what kdoc_output expects. + + required: + - name + - type + - declaration_start_line + + rst: + type: string + description: | + The expected output for RestOutput class. + + man: + type: string + description: | + The expected output for ManOutput class. + + anyOf: + required: kdoc_item + required: source + + required: + - name + - fname + - expected From 8b69f5225aebbe37c767021bee1b95642ce530ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:11 +0100 Subject: [PATCH 110/162] docs: add a simple kdoc-test.yaml together with a validation tool Create a simple kdoc-test.yaml to be used to create unit tests for kernel-doc parser and output classes. For now, all we want is a simple function mapped on a yaml test using the defined schema. To be sure that the schema is followed, add an unittest for the file, which will also validate that the schema is properly parsed. It should be noticed that the .TH definition for the man format contains a timestamp. We'll need to handle that when dealing with the actual implementation for the ManOutput class unit tests. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <74883976348c964f00161696d525c33ddd8c7641.1773823995.git.mchehab+huawei@kernel.org> --- tools/unittests/kdoc-test.yaml | 154 +++++++++++++++++++++++ tools/unittests/test_kdoc_test_schema.py | 94 ++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 tools/unittests/kdoc-test.yaml create mode 100755 tools/unittests/test_kdoc_test_schema.py diff --git a/tools/unittests/kdoc-test.yaml b/tools/unittests/kdoc-test.yaml new file mode 100644 index 000000000000..b6e04f10ccdb --- /dev/null +++ b/tools/unittests/kdoc-test.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026: Mauro Carvalho Chehab + +# Test cases for the dynamic tests. +# Useful to test if kernel-doc classes are doing what it is expected. +# + +tests: +- name: func1 + fname: mock_functions.c + description: "Simplest function test: do nothing, just rst output" + + source: | + /** + * func1 - Not exported function + * @arg1: @arg1 does nothing + * + * Does nothing + * + * return: + * always return 0. + */ + int func1(char *arg1) { return 0; }; + + + expected: + - rst: | + .. c:function:: int func1 (char *arg1) + + Not exported function + + .. container:: kernelindent + + **Parameters** + + ``char *arg1`` + **arg1** does nothing + + **Description** + + Does nothing + + **Return** + + always return 0. + + # TODO: how to handle timestamps at .TH? + man: | + .TH "func1" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + func1 \- Not exported function + .SH SYNOPSIS + .B "int" func1 + .BI "(char *arg1 " ");" + .SH ARGUMENTS + .IP "arg1" 12 + \fIarg1\fP does nothing + .SH "DESCRIPTION" + Does nothing + .SH "RETURN" + always return 0. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_functions.c\fR + +- name: func2 + fname: func2.c + description: Simple test with exports + + source: | + /** + * func2() - Exported function + * @arg1: @arg1 does nothing + * + * Does nothing + * + * return: + * always return 0. + */ + int func2(char *arg1) { return 0; }; + EXPORT_SYMBOL(func2); + + exports: func2 + expected: + - kdoc_item: + name: func2 + type: function + declaration_start_line: 1 + + sections: + Description: | + Does nothing + + Return: | + always return 0. + + sections_start_lines: + Description: 3 + Return: 6 + + parameterdescs: + arg1: | + @arg1 does nothing + parameterlist: + - arg1 + parameterdesc_start_lines: + arg1: 2 + parametertypes: + arg1: char *arg1 + + other_stuff: + func_macro: false + functiontype: int + purpose: "Exported function" + typedef: false + + rst: | + .. c:function:: int func2 (char *arg1) + + Exported function + + .. container:: kernelindent + + **Parameters** + + ``char *arg1`` + **arg1** does nothing + + **Description** + + Does nothing + + **Return** + + always return 0. + + # TODO: how to handle timestamps at .TH? + man: | + .TH "func2" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + func2 \- Exported function + .SH SYNOPSIS + .B "int" func2 + .BI "(char *arg1 " ");" + .SH ARGUMENTS + .IP "arg1" 12 + \fIarg1\fP does nothing + .SH "DESCRIPTION" + Does nothing + .SH "RETURN" + always return 0. + .SH "SEE ALSO" + .PP + Kernel file \fBfunc2.c\fR diff --git a/tools/unittests/test_kdoc_test_schema.py b/tools/unittests/test_kdoc_test_schema.py new file mode 100755 index 000000000000..9eceeba00440 --- /dev/null +++ b/tools/unittests/test_kdoc_test_schema.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +""" +Unit‑test driver for kernel‑doc YAML tests. + +Two kinds of tests are defined: + +* **Schema‑validation tests** – if ``jsonschema`` is available, the + YAML files in this directory are validated against the JSON‑Schema + described in ``kdoc-test-schema.yaml``. When the library is not + present, a warning is emitted and the validation step is simply + skipped – the dynamic kernel‑doc tests still run. + +* **Kernel‑doc tests** – dynamically generate one test method per + scenario in ``kdoc-test.yaml``. Each method simply forwards + the data to ``self.run_test`` – you only need to implement that + helper in your own code. + +File names are kept as module‑level constants so that the +implementation stays completely independent of ``pathlib``. +""" + +import os +import sys +import warnings +import yaml +import unittest +from typing import Any, Dict, List + +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) + +from unittest_helper import run_unittest + + +# +# Files to read +# +BASE = os.path.realpath(os.path.dirname(__file__)) + +SCHEMA_FILE = os.path.join(BASE, "kdoc-test-schema.yaml") +TEST_FILE = os.path.join(BASE, "kdoc-test.yaml") + +# +# Schema‑validation test +# +class TestYAMLSchemaValidation(unittest.TestCase): + """ + Checks if TEST_FILE matches SCHEMA_FILE. + """ + + @classmethod + def setUpClass(cls): + """ + Import jsonschema if available. + """ + + try: + from jsonschema import Draft7Validator + except ImportError: + print("Warning: jsonschema package not available. Skipping schema validation") + cls.validator = None + return + + with open(SCHEMA_FILE, encoding="utf-8") as fp: + cls.schema = yaml.safe_load(fp) + + cls.validator = Draft7Validator(cls.schema) + + def test_kdoc_test_yaml_followsschema(self): + """ + Run jsonschema validation if the validator is available. + If not, emit a warning and return without failing. + """ + if self.validator is None: + return + + with open(TEST_FILE, encoding="utf-8") as fp: + data = yaml.safe_load(fp) + + errors = self.validator.iter_errors(data) + + msgs = [] + for error in errors: + msgs.append(error.message) + + if msgs: + self.fail("Schema validation failed:\n\t" + "\n\t".join(msgs)) + +# -------------------------------------------------------------------- +# Entry point +# -------------------------------------------------------------------- +if __name__ == "__main__": + run_unittest(__file__) From eea0d807dbd42b411ae0df21c6ca8d3560cb9fbf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:12 +0100 Subject: [PATCH 111/162] docs: test_kdoc_parser: add support for dynamic test creation Use the content of kdoc-test.yaml to generate unittests to verify that kernel-doc internal methods are parsing C code and generating output the expected way. Depending on what is written at the parser file at kdoc-test.yaml, up to 5 tests can be generated from a single test entry inside the YAML file: 1. from source to kdoc_item: test KernelDoc class; 2. from kdoc_item to man: test ManOutput class; 3. from kdoc_item to rst: test RestOutput class; 4. from source to man without checking expected KdocItem; 5. from source to rst without checking expected KdocItem. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <7ec2593c5b19de3e3b1d8de92675f6b751d3fa21.1773823995.git.mchehab+huawei@kernel.org> --- tools/unittests/test_kdoc_parser.py | 368 ++++++++++++++++++++++++++-- 1 file changed, 350 insertions(+), 18 deletions(-) diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py index 26f74666a000..723dd8c7f4f3 100755 --- a/tools/unittests/test_kdoc_parser.py +++ b/tools/unittests/test_kdoc_parser.py @@ -8,24 +8,43 @@ Unit tests for kernel-doc parser. """ +import logging import os -import unittest import re +import shlex import sys +import unittest from textwrap import dedent from unittest.mock import patch, MagicMock, mock_open +import yaml + SRC_DIR = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(SRC_DIR, "../lib/python")) -from kdoc.kdoc_parser import KernelDoc +from kdoc.kdoc_files import KdocConfig from kdoc.kdoc_item import KdocItem +from kdoc.kdoc_parser import KernelDoc +from kdoc.kdoc_output import RestFormat, ManFormat + from kdoc.xforms_lists import CTransforms + from unittest_helper import run_unittest + +# +# Test file +# +TEST_FILE = os.path.join(SRC_DIR, "kdoc-test.yaml") + +# +# Ancillary logic to clean whitespaces +# #: Regex to help cleaning whitespaces -RE_WHITESPC = re.compile(r"\s++") +RE_WHITESPC = re.compile(r"[ \t]++") +RE_BEGINSPC = re.compile(r"^\s+", re.MULTILINE) +RE_ENDSPC = re.compile(r"\s+$", re.MULTILINE) def clean_whitespc(val, relax_whitespace=False): """ @@ -38,7 +57,9 @@ def clean_whitespc(val, relax_whitespace=False): if isinstance(val, str): val = val.strip() if relax_whitespace: - val = RE_WHITESPC.sub("", val) + val = RE_WHITESPC.sub(" ", val) + val = RE_BEGINSPC.sub("", val) + val = RE_ENDSPC.sub("", val) elif isinstance(val, list): val = [clean_whitespc(item, relax_whitespace) for item in val] elif isinstance(val, dict): @@ -46,22 +67,59 @@ def clean_whitespc(val, relax_whitespace=False): return val # -# Helper class to help mocking with +# Helper classes to help mocking with logger and config # -class KdocParser(unittest.TestCase): +class MockLogging(logging.Handler): + """ + Simple class to store everything on a list + """ + + def __init__(self, level=logging.NOTSET): + super().__init__(level) + self.messages = [] + self.formatter = logging.Formatter() + + def emit(self, record: logging.LogRecord) -> None: + """ + Append a formatted record to self.messages. + """ + try: + # The `format` method uses the handler's formatter. + message = self.format(record) + self.messages.append(message) + except Exception: + self.handleError(record) + +class MockKdocConfig(KdocConfig): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.log = logging.getLogger(__file__) + self.handler = MockLogging() + self.log.addHandler(self.handler) + + def warning(self, msg): + """Ancillary routine to output a warning and increment error count.""" + + self.log.warning(msg) + +# +# Helper class to generate KdocItem and validate its contents +# +# TODO: check self.config.handler.messages content +# +class GenerateKdocItem(unittest.TestCase): """ Base class to run KernelDoc parser class """ DEFAULT = vars(KdocItem("", "", "", 0)) + config = MockKdocConfig() + xforms = CTransforms() + def setUp(self): self.maxDiff = None - self.config = MagicMock() - self.config.log = MagicMock() - self.config.log.debug = MagicMock() - self.xforms = CTransforms() - def run_test(self, source, __expected_list, exports={}, fname="test.c", relax_whitespace=False): @@ -75,6 +133,9 @@ class KdocParser(unittest.TestCase): # Ensure that default values will be there expected_list = [] for e in __expected_list: + if not isinstance(e, dict): + e = vars(e) + new_e = self.DEFAULT.copy() new_e["fname"] = fname for key, value in e.items(): @@ -111,13 +172,155 @@ class KdocParser(unittest.TestCase): self.assertEqual(result, value, msg=f"at {key}") +# +# Ancillary function that replicates kdoc_files way to generate output +# +def cleanup_timestamp(text): + lines = text.split("\n") + + for i, line in enumerate(lines): + if not line.startswith('.TH'): + continue + + parts = shlex.split(line) + if len(parts) > 3: + parts[3] = "" + + lines[i] = " ".join(parts) + + + return "\n".join(lines) + +def gen_output(fname, out_style, symbols, expected, + config=None, relax_whitespace=False): + """ + Use the output class to return an output content from KdocItem symbols. + """ + + if not config: + config = MockKdocConfig() + + out_style.set_config(config) + + msg = out_style.output_symbols(fname, symbols) + + result = clean_whitespc(msg, relax_whitespace) + result = cleanup_timestamp(result) + + expected = clean_whitespc(expected, relax_whitespace) + expected = cleanup_timestamp(expected) + + return result, expected # -# Selttest class +# Classes to be used by dynamic test generation from YAML # -class TestSelfValidate(KdocParser): +class CToKdocItem(GenerateKdocItem): + def setUp(self): + self.maxDiff = None + + def run_parser_test(self, source, symbols, exports, fname): + if isinstance(symbols, dict): + symbols = [symbols] + + if isinstance(exports, str): + exports=set([exports]) + elif isinstance(exports, list): + exports=set(exports) + + self.run_test(source, symbols, exports=exports, + fname=fname, relax_whitespace=True) + +class KdocItemToMan(unittest.TestCase): + out_style = ManFormat() + + def setUp(self): + self.maxDiff = None + + def run_out_test(self, fname, symbols, expected): + """ + Generate output using out_style, + """ + result, expected = gen_output(fname, self.out_style, + symbols, expected) + + self.assertEqual(result, expected) + +class KdocItemToRest(unittest.TestCase): + out_style = RestFormat() + + def setUp(self): + self.maxDiff = None + + def run_out_test(self, fname, symbols, expected): + """ + Generate output using out_style, + """ + result, expected = gen_output(fname, self.out_style, symbols, + expected, relax_whitespace=True) + + self.assertEqual(result, expected) + + +class CToMan(unittest.TestCase): + out_style = ManFormat() + config = MockKdocConfig() + xforms = CTransforms() + + def setUp(self): + self.maxDiff = None + + def run_out_test(self, fname, source, expected): + """ + Generate output using out_style, + """ + patcher = patch('builtins.open', + new_callable=mock_open, read_data=source) + + kernel_doc = KernelDoc(self.config, fname, self.xforms) + + with patcher: + export_table, entries = kernel_doc.parse_kdoc() + + result, expected = gen_output(fname, self.out_style, + entries, expected, config=self.config) + + self.assertEqual(result, expected) + + +class CToRest(unittest.TestCase): + out_style = RestFormat() + config = MockKdocConfig() + xforms = CTransforms() + + def setUp(self): + self.maxDiff = None + + def run_out_test(self, fname, source, expected): + """ + Generate output using out_style, + """ + patcher = patch('builtins.open', + new_callable=mock_open, read_data=source) + + kernel_doc = KernelDoc(self.config, fname, self.xforms) + + with patcher: + export_table, entries = kernel_doc.parse_kdoc() + + result, expected = gen_output(fname, self.out_style, entries, + expected, relax_whitespace=True, + config=self.config) + + self.assertEqual(result, expected) + + +# +# Selftest class +# +class TestSelfValidate(GenerateKdocItem): """ - Tests to check if logic inside KdocParser.run_test() is working. + Tests to check if logic inside GenerateKdocItem.run_test() is working. """ SOURCE = """ @@ -147,16 +350,23 @@ class TestSelfValidate(KdocParser): 'Description': 'Does nothing\n\n', 'Return': '\nalways return 0.\n' }, + + 'sections_start_lines': { + 'Description': 4, + 'Return': 7, + }, + + 'parameterdescs': {'arg1': '@arg1 does nothing\n'}, + 'parameterlist': ['arg1'], + 'parameterdesc_start_lines': {'arg1': 3}, + 'parametertypes': {'arg1': 'char *arg1'}, + 'other_stuff': { 'func_macro': False, 'functiontype': 'int', 'purpose': 'Exported function', 'typedef': False }, - 'parameterdescs': {'arg1': '@arg1 does nothing\n'}, - 'parameterlist': ['arg1'], - 'parameterdesc_start_lines': {'arg1': 3}, - 'parametertypes': {'arg1': 'char *arg1'}, }] EXPORTS = {"function3"} @@ -195,6 +405,128 @@ class TestSelfValidate(KdocParser): """ self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS) +# +# Class and logic to create dynamic tests from YAML +# + +class KernelDocDynamicTests(): + """ + Dynamically create a set of tests from a YAML file. + """ + + @classmethod + def create_parser_test(cls, name, fname, source, symbols, exports): + """ + Return a function that will be attached to the test class. + """ + def test_method(self): + """Lambda-like function to run tests with provided vars""" + self.run_parser_test(source, symbols, exports, fname) + + test_method.__name__ = f"test_gen_{name}" + + setattr(CToKdocItem, test_method.__name__, test_method) + + @classmethod + def create_out_test(cls, name, fname, symbols, out_type, data): + """ + Return a function that will be attached to the test class. + """ + def test_method(self): + """Lambda-like function to run tests with provided vars""" + self.run_out_test(fname, symbols, data) + + test_method.__name__ = f"test_{out_type}_{name}" + + if out_type == "man": + setattr(KdocItemToMan, test_method.__name__, test_method) + else: + setattr(KdocItemToRest, test_method.__name__, test_method) + + @classmethod + def create_src2out_test(cls, name, fname, source, out_type, data): + """ + Return a function that will be attached to the test class. + """ + def test_method(self): + """Lambda-like function to run tests with provided vars""" + self.run_out_test(fname, source, data) + + test_method.__name__ = f"test_{out_type}_{name}" + + if out_type == "man": + setattr(CToMan, test_method.__name__, test_method) + else: + setattr(CToRest, test_method.__name__, test_method) + + @classmethod + def create_tests(cls): + """ + Iterate over all scenarios and add a method to the class for each. + + The logic in this function assumes a valid test that are compliant + with kdoc-test-schema.yaml. There is an unit test to check that. + As such, it picks mandatory values directly, and uses get() for the + optional ones. + """ + + with open(TEST_FILE, encoding="utf-8") as fp: + testset = yaml.safe_load(fp) + + tests = testset["tests"] + + for idx, test in enumerate(tests): + name = test["name"] + fname = test["fname"] + source = test["source"] + expected_list = test["expected"] + + exports = test.get("exports", []) + + # + # The logic below allows setting up to 5 types of test: + # 1. from source to kdoc_item: test KernelDoc class; + # 2. from kdoc_item to man: test ManOutput class; + # 3. from kdoc_item to rst: test RestOutput class; + # 4. from source to man without checking expected KdocItem; + # 5. from source to rst without checking expected KdocItem. + # + for expected in expected_list: + kdoc_item = expected.get("kdoc_item") + man = expected.get("man", []) + rst = expected.get("rst", []) + + if kdoc_item: + if isinstance(kdoc_item, dict): + kdoc_item = [kdoc_item] + + symbols = [] + + for arg in kdoc_item: + arg["fname"] = fname + arg["start_line"] = 1 + + symbols.append(KdocItem.from_dict(arg)) + + if source: + cls.create_parser_test(name, fname, source, + symbols, exports) + + if man: + cls.create_out_test(name, fname, symbols, "man", man) + + if rst: + cls.create_out_test(name, fname, symbols, "rst", rst) + + elif source: + if man: + cls.create_src2out_test(name, fname, source, "man", man) + + if rst: + cls.create_src2out_test(name, fname, source, "rst", rst) + +KernelDocDynamicTests.create_tests() + # # Run all tests # From b37b3cbbb1f1a99bc8b95d9f00fcf887c27f4770 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:13 +0100 Subject: [PATCH 112/162] docs: add a new file to write kernel-doc output to a YAML file Storing kernel-doc output is helpful to allow debugging problems on it and to preparate unit tests. Add a class to store such contents at the same format as defined at kdoc-test-schema.yaml. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <5d084ca1a91f6a620534a1135d1b8183d934319a.1773823995.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_yaml_file.py | 155 ++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tools/lib/python/kdoc/kdoc_yaml_file.py diff --git a/tools/lib/python/kdoc/kdoc_yaml_file.py b/tools/lib/python/kdoc/kdoc_yaml_file.py new file mode 100644 index 000000000000..db131503c3f6 --- /dev/null +++ b/tools/lib/python/kdoc/kdoc_yaml_file.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . + +import os + +from kdoc.kdoc_output import ManFormat, RestFormat + + +class KDocTestFile(): + """ + Handles the logic needed to store kernel‑doc output inside a YAML file. + Useful for unit tests and regression tests. + """ + + def __init__(self, config, yaml_file, yaml_content): + # + # Bail out early if yaml is not available + # + try: + import yaml + except ImportError: + sys.exit("Warning: yaml package not available. Aborting it.") + + self.config = config + self.test_file = os.path.expanduser(yaml_file) + self.yaml_content = yaml_content + + self.tests = [] + + out_dir = os.path.dirname(self.test_file) + if out_dir and not os.path.isdir(out_dir): + sys.exit(f"Directory {out_dir} doesn't exist.") + + self.out_style = [] + + if "man" in self.yaml_content: + out_style = ManFormat() + out_style.set_config(self.config) + + self.out_style.append(out_style) + + if "rst" in self.yaml_content: + out_style = RestFormat() + out_style.set_config(self.config) + + self.out_style.append(out_style) + + def set_filter(self, export, internal, symbol, nosymbol, + function_table, enable_lineno, no_doc_sections): + """ + Set filters at the output classes. + """ + for out_style in self.out_style: + out_style.set_filter(export, internal, symbol, + nosymbol, function_table, + enable_lineno, no_doc_sections) + + @staticmethod + def get_kdoc_item(arg, start_line=1): + + d = vars(arg) + + declaration_start_line = d.get("declaration_start_line") + if not declaration_start_line: + return d + + d["declaration_start_line"] = start_line + + parameterdesc_start_lines = d.get("parameterdesc_start_lines") + if parameterdesc_start_lines: + for key in parameterdesc_start_lines: + ln = parameterdesc_start_lines[key] + ln += start_line - declaration_start_line + + parameterdesc_start_lines[key] = ln + + sections_start_lines = d.get("sections_start_lines") + if sections_start_lines: + for key in sections_start_lines: + ln = sections_start_lines[key] + ln += start_line - declaration_start_line + + sections_start_lines[key] = ln + + return d + + def output_symbols(self, fname, symbols, source): + """ + Store source, symbols and output strings at self.tests. + """ + + # + # KdocItem needs to be converted into dicts + # + kdoc_item = [] + expected = [] + + if not symbols and not source: + return + + if not source or len(symbols) != len(source): + print(f"Warning: lengths are different. Ignoring {fname}") + + # Folding without line numbers is too hard. + # The right thing to do here to proceed would be to delete + # not-handled source blocks, as len(source) should be bigger + # than len(symbols) + return + + base_name = "test_" + fname.replace(".", "_").replace("/", "_") + expected_dict = {} + start_line=1 + + for i in range(0, len(symbols)): + arg = symbols[i] + + if "KdocItem" in self.yaml_content: + msg = self.get_kdoc_item(arg) + + expected_dict["kdoc_item"] = msg + + for out_style in self.out_style: + if isinstance(out_style, ManFormat): + key = "man" + else: + key = "rst" + + expected_dict[key]= out_style.output_symbols(fname, [arg]) + + name = f"{base_name}_{i:03d}" + + test = { + "name": name, + "description": f"{fname} line {source[i]["ln"]}", + "fname": fname, + "source": source[i]["data"], + "expected": [expected_dict] + } + + self.tests.append(test) + + expected_dict = {} + + def write(self): + """ + Output the content of self.tests to self.test_file. + """ + import yaml + + data = {"tests": self.tests} + + with open(self.test_file, "w", encoding="utf-8") as fp: + yaml.safe_dump(data, fp, sort_keys=False, default_style="|", + default_flow_style=False, allow_unicode=True) From 01d6d7bf9672f1aeabbffaa3fbfb8017223ff878 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2026 10:11:14 +0100 Subject: [PATCH 113/162] docs: kernel-doc: add support to store output on a YAML file Add a command line parameter and library support to optionally store: - KdocItem intermediate format after parsing; - man pages output; - rst output. inside a YAML file. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/docs/kernel-doc | 48 +++++++++++++++++++++++----- tools/lib/python/kdoc/kdoc_files.py | 47 +++++++++++++++++++++++---- tools/lib/python/kdoc/kdoc_parser.py | 27 +++++++++++++++- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/tools/docs/kernel-doc b/tools/docs/kernel-doc index 3a932f95bdf5..d9192c3f1645 100755 --- a/tools/docs/kernel-doc +++ b/tools/docs/kernel-doc @@ -240,11 +240,9 @@ def main(): help=EXPORT_FILE_DESC) # - # Output format mutually-exclusive group + # Output format # - out_group = parser.add_argument_group("Output format selection (mutually exclusive)") - - out_fmt = out_group.add_mutually_exclusive_group() + out_fmt = parser.add_argument_group("Output format selection (mutually exclusive)") out_fmt.add_argument("-m", "-man", "--man", action="store_true", help="Output troff manual page format.") @@ -253,6 +251,12 @@ def main(): out_fmt.add_argument("-N", "-none", "--none", action="store_true", help="Do not output documentation, only warnings.") + out_fmt.add_argument("-y", "--yaml-file", "--yaml", + help="Stores kernel-doc output on a yaml file.") + out_fmt.add_argument("-k", "--kdoc-item", "--kdoc", action="store_true", + help="Store KdocItem inside yaml file. Ued together with --yaml.") + + # # Output selection mutually-exclusive group # @@ -323,14 +327,42 @@ def main(): from kdoc.kdoc_files import KernelFiles # pylint: disable=C0415 from kdoc.kdoc_output import RestFormat, ManFormat # pylint: disable=C0415 - if args.man: - out_style = ManFormat(modulename=args.modulename) - elif args.none: + yaml_content = set() + if args.yaml_file: out_style = None + + if args.man: + yaml_content |= {"man"} + + if args.rst: + yaml_content |= {"rst"} + + if args.kdoc_item or not yaml_content: + yaml_content |= {"KdocItem"} + else: - out_style = RestFormat() + n_outputs = 0 + + if args.man: + out_style = ManFormat(modulename=args.modulename) + n_outputs += 1 + + if args.none: + out_style = None + n_outputs += 1 + + if args.rst or n_outputs == 0: + n_outputs += 1 + out_style = RestFormat() + + if n_outputs > 1: + parser.error("Those arguments are muttually exclusive: --man, --rst, --none, except when generating a YAML file.") + + elif not n_outputs: + out_style = RestFormat() kfiles = KernelFiles(verbose=args.verbose, + yaml_file=args.yaml_file, yaml_content=yaml_content, out_style=out_style, werror=args.werror, wreturn=args.wreturn, wshort_desc=args.wshort_desc, wcontents_before_sections=args.wcontents_before_sections) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 58f4ee08e226..5a299ed44d62 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -16,6 +16,7 @@ import re from kdoc.kdoc_parser import KernelDoc from kdoc.xforms_lists import CTransforms from kdoc.kdoc_output import OutputFormat +from kdoc.kdoc_yaml_file import KDocTestFile class GlobSourceFiles: @@ -152,6 +153,12 @@ class KernelFiles(): If not specified, defaults to use: ``logging.getLogger("kernel-doc")`` + ``yaml_file`` + If defined, stores the output inside a YAML file. + + ``yaml_content`` + Defines what will be inside the YAML file. + Note: There are two type of parsers defined here: @@ -181,7 +188,12 @@ class KernelFiles(): if fname in self.files: return - doc = KernelDoc(self.config, fname, self.xforms) + if self.test_file: + store_src = True + else: + store_src = False + + doc = KernelDoc(self.config, fname, self.xforms, store_src=store_src) export_table, entries = doc.parse_kdoc() self.export_table[fname] = export_table @@ -191,6 +203,10 @@ class KernelFiles(): self.results[fname] = entries + source = doc.get_source() + if source: + self.source[fname] = source + def process_export_file(self, fname): """ Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file. @@ -220,7 +236,7 @@ class KernelFiles(): def __init__(self, verbose=False, out_style=None, xforms=None, werror=False, wreturn=False, wshort_desc=False, wcontents_before_sections=False, - logger=None): + yaml_file=None, yaml_content=None, logger=None): """ Initialize startup variables and parse all files. """ @@ -259,6 +275,11 @@ class KernelFiles(): # Override log warning, as we want to count errors self.config.warning = self.warning + if yaml_file: + self.test_file = KDocTestFile(self.config, yaml_file, yaml_content) + else: + self.test_file = None + if xforms: self.xforms = xforms else: @@ -273,6 +294,7 @@ class KernelFiles(): self.errors = 0 self.results = {} + self.source = {} self.files = set() self.export_files = set() @@ -331,16 +353,29 @@ class KernelFiles(): for s in symbol: function_table.add(s) - self.out_style.set_filter(export, internal, symbol, nosymbol, - function_table, enable_lineno, - no_doc_sections) - if fname not in self.results: self.config.log.warning("No kernel-doc for file %s", fname) continue symbols = self.results[fname] + if self.test_file: + self.test_file.set_filter(export, internal, symbol, nosymbol, + function_table, enable_lineno, + no_doc_sections) + + self.test_file.output_symbols(fname, symbols, + self.source.get(fname)) + + continue + + self.out_style.set_filter(export, internal, symbol, nosymbol, + function_table, enable_lineno, + no_doc_sections) + msg = self.out_style.output_symbols(fname, symbols) if msg: yield fname, msg + + if self.test_file: + self.test_file.write() diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index 35658a7e72d5..a10e64589d76 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -246,12 +246,13 @@ class KernelDoc: #: String to write when a parameter is not described. undescribed = "-- undescribed --" - def __init__(self, config, fname, xforms): + def __init__(self, config, fname, xforms, store_src=False): """Initialize internal variables""" self.fname = fname self.config = config self.xforms = xforms + self.store_src = store_src tokenizer_set_log(self.config.log, f"{self.fname}: CMatch: ") @@ -264,6 +265,9 @@ class KernelDoc: # Place all potential outputs into an array self.entries = [] + # When store_src is true, the kernel-doc source content is stored here + self.source = None + # # We need Python 3.7 for its "dicts remember the insertion # order" guarantee @@ -1592,6 +1596,15 @@ class KernelDoc: state.DOCBLOCK: process_docblock, } + def get_source(self): + """ + Return the file content of the lines handled by kernel-doc at the + latest parse_kdoc() run. + + Returns none if KernelDoc() was not initialized with store_src, + """ + return self.source + def parse_kdoc(self): """ Open and process each line of a C source file. @@ -1605,6 +1618,8 @@ class KernelDoc: prev = "" prev_ln = None export_table = set() + self.source = [] + self.state = state.NORMAL try: with open(self.fname, "r", encoding="utf8", @@ -1631,6 +1646,8 @@ class KernelDoc: ln, state.name[self.state], line) + prev_state = self.state + # This is an optimization over the original script. # There, when export_file was used for the same file, # it was read twice. Here, we use the already-existing @@ -1641,6 +1658,14 @@ class KernelDoc: # Hand this line to the appropriate state handler self.state_actions[self.state](self, ln, line) + if self.store_src and prev_state != self.state or self.state != state.NORMAL: + if self.state == state.NAME: + # A "/**" was detected. Add a new source element + self.source.append({"ln": ln, "data": line + "\n"}) + else: + # Append to the existing one + self.source[-1]["data"] += line + "\n" + self.emit_unused_warnings() except OSError: From 99aa500409c43573a0399b2bd0dcf64e0062347c Mon Sep 17 00:00:00 2001 From: Rito Rhymes Date: Sat, 21 Mar 2026 08:55:32 -0400 Subject: [PATCH 114/162] docs: use logo.svg as favicon Use the existing documentation logo as the HTML favicon. This makes generated documentation pages use a matching browser tab icon without introducing a separate favicon asset. Signed-off-by: Rito Rhymes Signed-off-by: Jonathan Corbet Message-ID: <20260321125532.9568-1-rito@ritovision.com> --- Documentation/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/conf.py b/Documentation/conf.py index 679861503a25..9b822ab470d9 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -455,6 +455,7 @@ if html_theme == "alabaster": # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = "images/logo.svg" +html_favicon = "images/logo.svg" # Output file base name for HTML help builder. htmlhelp_basename = "TheLinuxKerneldoc" From 19dcccbc064d6c58eaafae1ecb94821a2535cc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Pando?= Date: Tue, 24 Mar 2026 17:36:04 +0100 Subject: [PATCH 115/162] docs: driver-api: fix 6 spelling typos in Documentation/driver-api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix minor spelling mistakes in the driver-api documentation. These changes improve readability in ACPI, CXL, DMA and PCI docs. Reviewed-by: Randy Dunlap Signed-off-by: Tomás Pando Signed-off-by: Jonathan Corbet Message-ID: <20260324163604.5710-1-tovictakamine@gmail.com> --- Documentation/driver-api/acpi/acpi-drivers.rst | 2 +- Documentation/driver-api/cxl/platform/acpi/cedt.rst | 2 +- Documentation/driver-api/cxl/platform/bios-and-efi.rst | 2 +- Documentation/driver-api/dmaengine/pxa_dma.rst | 2 +- Documentation/driver-api/libata.rst | 2 +- Documentation/driver-api/pci/p2pdma.rst | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/driver-api/acpi/acpi-drivers.rst b/Documentation/driver-api/acpi/acpi-drivers.rst index b1fbbddb8b4f..376b6d8a678c 100644 --- a/Documentation/driver-api/acpi/acpi-drivers.rst +++ b/Documentation/driver-api/acpi/acpi-drivers.rst @@ -47,7 +47,7 @@ generally be avoided and so struct acpi_driver objects should not be used. Moreover, a device ID is necessary to bind a driver directly to an ACPI device node, but device IDs are not generally associated with all of them. Some of them contain alternative information allowing the corresponding pieces of -hardware to be identified, for example represeted by an _ADR object return +hardware to be identified, for example represented by an _ADR object return value, and device IDs are not used in those cases. In consequence, confusingly enough, binding an ACPI driver to an ACPI device node may even be impossible. diff --git a/Documentation/driver-api/cxl/platform/acpi/cedt.rst b/Documentation/driver-api/cxl/platform/acpi/cedt.rst index 1d9c9d3592dc..217a75fb4881 100644 --- a/Documentation/driver-api/cxl/platform/acpi/cedt.rst +++ b/Documentation/driver-api/cxl/platform/acpi/cedt.rst @@ -55,7 +55,7 @@ voltile vs persistent, etc). One or more bits may be set. :: Bit[1]: CXL Type 3 Memory Bit[2]: Volatile Memory Bit[3]: Persistent Memory - Bit[4]: Fixed Config (HPA cannot be re-used) + Bit[4]: Fixed Config (HPA cannot be reused) INTRA-host-bridge interleave (multiple devices on one host bridge) is NOT reported in this structure, and is solely defined via CXL device decoder diff --git a/Documentation/driver-api/cxl/platform/bios-and-efi.rst b/Documentation/driver-api/cxl/platform/bios-and-efi.rst index a4b44c018f09..5d918b06f6c0 100644 --- a/Documentation/driver-api/cxl/platform/bios-and-efi.rst +++ b/Documentation/driver-api/cxl/platform/bios-and-efi.rst @@ -277,7 +277,7 @@ The CFMWS field of the CEDT has special restriction bits which describe whether the described memory region allows volatile or persistent memory (or both). If the platform intends to support either: -1) A device with multiple medias, or +1) A device with multiple media, or 2) Using a persistent memory device as normal memory A platform may wish to create multiple CEDT CFMWS entries to describe the same diff --git a/Documentation/driver-api/dmaengine/pxa_dma.rst b/Documentation/driver-api/dmaengine/pxa_dma.rst index 442ee691a190..8f9da66b0bfa 100644 --- a/Documentation/driver-api/dmaengine/pxa_dma.rst +++ b/Documentation/driver-api/dmaengine/pxa_dma.rst @@ -40,7 +40,7 @@ Design ====== a) Virtual channels Same concept as in sa11x0 driver, ie. a driver was assigned a "virtual -channel" linked to the requestor line, and the physical DMA channel is +channel" linked to the requester line, and the physical DMA channel is assigned on the fly when the transfer is issued. b) Transfer anatomy for a scatter-gather transfer diff --git a/Documentation/driver-api/libata.rst b/Documentation/driver-api/libata.rst index 93d97fe78e3f..28b8437f6e4f 100644 --- a/Documentation/driver-api/libata.rst +++ b/Documentation/driver-api/libata.rst @@ -286,7 +286,7 @@ and other exceptional conditions. The primary responsibility of an implementation is to call :c:func:`ata_std_error_handler`. :c:func:`ata_std_error_handler` will perform a standard error handling sequence -to resurect failed devices, detach lost devices and add new devices (if any). +to resurrect failed devices, detach lost devices and add new devices (if any). This function will call the various reset operations for a port, as needed. These operations are as follows. diff --git a/Documentation/driver-api/pci/p2pdma.rst b/Documentation/driver-api/pci/p2pdma.rst index 280673b50350..d3f406cca694 100644 --- a/Documentation/driver-api/pci/p2pdma.rst +++ b/Documentation/driver-api/pci/p2pdma.rst @@ -38,7 +38,7 @@ for all usage refcounts to reach zero. At the lowest level the P2P subsystem offers a naked struct p2p_provider that delegates lifecycle management to the providing driver. It is expected that drivers using this option will wrap their MMIO memory in DMABUF and use DMABUF -to provide an invalidation shutdown. These MMIO addresess have no struct page, and +to provide an invalidation shutdown. These MMIO addresses have no struct page, and if used with mmap() must create special PTEs. As such there are very few kernel uAPIs that can accept pointers to them; in particular they cannot be used with read()/write(), including O_DIRECT. From f2679ac773899f5fdea0b68d5077eef5f88dfd42 Mon Sep 17 00:00:00 2001 From: Rito Rhymes Date: Mon, 23 Mar 2026 11:14:01 -0400 Subject: [PATCH 116/162] docs: allow inline literals in paragraphs to wrap to prevent overflow Some documentation pages contain long inline literals in paragraph text that can force page-wide horizontal scroll overflow and break layout on smaller screens. Override the default `span.pre` white-space behavior for inline literals and use `overflow-wrap: anywhere` so they can wrap when needed. For code used as part of a paragraph, wrapping is appropriate because it is stylistically part of the surrounding text. Code blocks, by contrast, are meant to preserve formatting fidelity and are better served by contained horizontal scrolling. Examples: https://docs.kernel.org/6.15/userspace-api/futex2.html https://docs.kernel.org/6.15/security/IMA-templates.html Signed-off-by: Rito Rhymes Assisted-by: Codex:GPT-5.4 Tested-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260323151401.27415-1-rito@ritovision.com> --- Documentation/sphinx-static/custom.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css index db24f4344e6c..dd69df2a7f57 100644 --- a/Documentation/sphinx-static/custom.css +++ b/Documentation/sphinx-static/custom.css @@ -149,6 +149,15 @@ div.language-selection ul li:hover { background: #dddddd; } +/* + * Let long inline literals in paragraph text wrap as needed to prevent + * overflow. + */ +code.docutils.literal span.pre { + white-space: normal; + overflow-wrap: anywhere; +} + /* Make xrefs more universally visible */ a.reference, a.reference:hover { border-bottom: none; From 3aff388bc4e8d64583d144f3be9c0aff9a54f14d Mon Sep 17 00:00:00 2001 From: Rito Rhymes Date: Mon, 23 Mar 2026 11:33:42 -0400 Subject: [PATCH 117/162] docs: contain horizontal overflow in C API descriptions Some documentation pages contain long C API signatures that can exceed the content width and cause page-wide horizontal scroll overflow. Apply contained horizontal scrolling to C API description blocks and keep their signature rows on one line. This preserves signature formatting while preventing them from breaking page layout. Contained horizontal scrolling is preferred over wrapping here because code fidelity is the priority. These blocks are intended to remain representative of the code itself. Wrapping distorts spacing and line structure, which affects fidelity, creates misleading renderings, and reduces readability. Examples: https://docs.kernel.org/6.15/driver-api/regulator.html https://docs.kernel.org/6.15/userspace-api/fwctl/fwctl-cxl.html Signed-off-by: Rito Rhymes Assisted-by: Codex:GPT-5.4 Tested-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260323153342.33447-1-rito@ritovision.com> --- Documentation/sphinx-static/custom.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css index dd69df2a7f57..72e08782dd05 100644 --- a/Documentation/sphinx-static/custom.css +++ b/Documentation/sphinx-static/custom.css @@ -40,6 +40,13 @@ li { text-indent: 0em; } dl.function, dl.struct, dl.enum { margin-top: 2em; background-color: #ecf0f3; } /* indent lines 2+ of multi-line function prototypes */ dl.function dt { margin-left: 10em; text-indent: -10em; } +/* + * Preserve C API signatures on one line and apply contained horizontal + * scrolling to prevent them from exceeding their container width and + * breaking page layout. + */ +dl.c { overflow-x: auto; overflow-y: hidden; } +dl.c > dt.sig.sig-object { white-space: nowrap; } dt.sig-object { font-size: larger; } div.kernelindent { margin-left: 2em; margin-right: 4em; } From 127bdd9f12ae4e77cb74f06aa60e996a2d4baafa Mon Sep 17 00:00:00 2001 From: Rito Rhymes Date: Mon, 23 Mar 2026 11:24:28 -0400 Subject: [PATCH 118/162] docs: allow long table reference links to wrap and prevent overflow Some documentation pages contain docutils tables with reference links that use long unbroken strings. Those strings can expand the table width beyond the content column and cause page-wide horizontal overflow. Allow reference links in docutils tables in the main document body to wrap when needed so the table stays within the content column and does not break page layout. Examples: https://docs.kernel.org/6.15/arch/openrisc/openrisc_port.html https://docs.kernel.org/6.15/filesystems/ext2.html Signed-off-by: Rito Rhymes Assisted-by: Codex:GPT-5.4 Tested-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260323152428.30483-2-rito@ritovision.com> --- Documentation/sphinx-static/custom.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css index 72e08782dd05..cadc2fac7065 100644 --- a/Documentation/sphinx-static/custom.css +++ b/Documentation/sphinx-static/custom.css @@ -165,6 +165,11 @@ code.docutils.literal span.pre { overflow-wrap: anywhere; } +/* Let rendered reference links in tables wrap when needed. */ +div.body table.docutils a.reference { + overflow-wrap: anywhere; +} + /* Make xrefs more universally visible */ a.reference, a.reference:hover { border-bottom: none; From c464407ada06fdfc4d49bbb86085f02fd7f565c3 Mon Sep 17 00:00:00 2001 From: Rito Rhymes Date: Mon, 23 Mar 2026 11:24:27 -0400 Subject: [PATCH 119/162] docs: allow long links to wrap per character to prevent page overflow Some documentation pages contain long link text without natural break points, which can force page-wide horizontal scroll overflow on small screens. Use overflow-wrap: anywhere for anchor text in the docs stylesheet so links can wrap per character as a fallback when normal word boundaries are unavailable. Examples: https://docs.kernel.org/6.15/firmware-guide/acpi/non-d0-probe.html https://docs.kernel.org/6.15/arch/x86/earlyprintk.html Signed-off-by: Rito Rhymes Assisted-by: Codex:GPT-5.4 Tested-by: Randy Dunlap Acked-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260323152428.30483-1-rito@ritovision.com> --- Documentation/sphinx-static/custom.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css index cadc2fac7065..f91393426a50 100644 --- a/Documentation/sphinx-static/custom.css +++ b/Documentation/sphinx-static/custom.css @@ -170,6 +170,11 @@ div.body table.docutils a.reference { overflow-wrap: anywhere; } +/* Let long link text wrap instead of forcing overflow. */ +a { + overflow-wrap: anywhere; +} + /* Make xrefs more universally visible */ a.reference, a.reference:hover { border-bottom: none; From 625ce45f2c39bf5059d33de573da624f4b2988cb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:44 +0100 Subject: [PATCH 120/162] MAINTAINERS: update documentation scripts to add unittests Ensure that we'll receive e-mails for attempts to touch tools/unittests. While here, place entries alphabetically sorted. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <6be396b8423372dd006484351ca2dbc54220587e.1774256269.git.mchehab+huawei@kernel.org> --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c05a72245049..f0b106a4dd96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7679,8 +7679,9 @@ M: Mauro Carvalho Chehab L: linux-doc@vger.kernel.org S: Maintained F: Documentation/sphinx/ -F: tools/lib/python/* F: tools/docs/ +F: tools/lib/python/* +F: tools/unittests/* DOCUMENTATION/ITALIAN M: Federico Vaga From 3f049a5ba920f96df9eeb576d72c99535ab300f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:45 +0100 Subject: [PATCH 121/162] unittests: test_kdoc_parser: add command line arg to read a YAML file The test_kdoc_parser.py already supports loading dynamic tests when running unit tests. Add support to read from a different file. This is useful for: - regression tests before/afer some changes; - preparing new unit tests; - test a different yaml before adding its contents at tools/unittests/kdoc-test.yaml. It should be noticed that passing an argument to a unit test is not too trivial, as unittest core will load itself the runner with a separate environment. The best (only?) way to do it is by setting the system environment. This way, when the class is called by the unit test loader, it can pick the var from the environment without relying on a global variable. The unittest_helper has already provision for it, so let's use its support. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <1d1a56de012c43756f9ca87aa9bf6c285674f113.1774256269.git.mchehab+huawei@kernel.org> --- tools/unittests/test_kdoc_parser.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py index 723dd8c7f4f3..f2250ef192ce 100755 --- a/tools/unittests/test_kdoc_parser.py +++ b/tools/unittests/test_kdoc_parser.py @@ -30,7 +30,7 @@ from kdoc.kdoc_output import RestFormat, ManFormat from kdoc.xforms_lists import CTransforms -from unittest_helper import run_unittest +from unittest_helper import TestUnits # @@ -38,6 +38,10 @@ from unittest_helper import run_unittest # TEST_FILE = os.path.join(SRC_DIR, "kdoc-test.yaml") +env = { + "yaml_file": TEST_FILE +} + # # Ancillary logic to clean whitespaces # @@ -470,7 +474,9 @@ class KernelDocDynamicTests(): optional ones. """ - with open(TEST_FILE, encoding="utf-8") as fp: + test_file = os.environ.get("yaml_file", TEST_FILE) + + with open(test_file, encoding="utf-8") as fp: testset = yaml.safe_load(fp) tests = testset["tests"] @@ -531,4 +537,15 @@ KernelDocDynamicTests.create_tests() # Run all tests # if __name__ == "__main__": - run_unittest(__file__) + runner = TestUnits() + parser = runner.parse_args() + parser.add_argument("-y", "--yaml-file", "--yaml", + help='Name of the yaml file to load') + + args = parser.parse_args() + + if args.yaml_file: + env["yaml_file"] = os.path.expanduser(args.yaml_file) + + # Run tests with customized arguments + runner.run(__file__, parser=parser, args=args, env=env) From e896174e466f593f3a62fd4dd779e6686bf32f40 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:46 +0100 Subject: [PATCH 122/162] docs: tools: include kdoc_yaml_file at documentation Add an autodoc entry for the new kdoc_yaml_file module. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <32b86abe7acee2dd4f73a35836ec94e8690f04cd.1774256269.git.mchehab+huawei@kernel.org> --- Documentation/tools/kdoc_ancillary.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/tools/kdoc_ancillary.rst b/Documentation/tools/kdoc_ancillary.rst index 85f3806a431a..249753744d11 100644 --- a/Documentation/tools/kdoc_ancillary.rst +++ b/Documentation/tools/kdoc_ancillary.rst @@ -53,3 +53,11 @@ Python version ancillary methods :members: :show-inheritance: :undoc-members: + +Write output on YAML file +========================= + +.. automodule:: lib.python.kdoc.kdoc_yaml_file + :members: + :show-inheritance: + :undoc-members: From 6e0d7b63676b85490bbaf01c9a8ebcd692bed981 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:47 +0100 Subject: [PATCH 123/162] docs: kdoc_yaml_file: add a representer to make strings look nicer The strings representation is not ok, currently. Add a helper function to improve it, and drop blank lines at beginning and at the end of the dumps Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <422041a8b49b2609de5749092fe074b7948c32a6.1774256269.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_yaml_file.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_yaml_file.py b/tools/lib/python/kdoc/kdoc_yaml_file.py index db131503c3f6..18737abb1176 100644 --- a/tools/lib/python/kdoc/kdoc_yaml_file.py +++ b/tools/lib/python/kdoc/kdoc_yaml_file.py @@ -126,7 +126,7 @@ class KDocTestFile(): else: key = "rst" - expected_dict[key]= out_style.output_symbols(fname, [arg]) + expected_dict[key]= out_style.output_symbols(fname, [arg]).strip() name = f"{base_name}_{i:03d}" @@ -148,8 +148,20 @@ class KDocTestFile(): """ import yaml + # Helper function to better handle multilines + def str_presenter(dumper, data): + if "\n" in data: + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") + + return dumper.represent_scalar("tag:yaml.org,2002:str", data) + + # Register the representer + yaml.add_representer(str, str_presenter) + data = {"tests": self.tests} with open(self.test_file, "w", encoding="utf-8") as fp: - yaml.safe_dump(data, fp, sort_keys=False, default_style="|", - default_flow_style=False, allow_unicode=True) + yaml.dump(data, fp, + sort_keys=False, width=120, indent=2, + default_flow_style=False, allow_unicode=True, + explicit_start=False, explicit_end=False) From bc63427c4d1031c761639aa42ae5a77beabfa98b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:48 +0100 Subject: [PATCH 124/162] docs: kdoc-test.yaml: add more tests Add extra tests to check if the new "var" type is properly handled and to cover mutex context annotations. Co-developed-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <75af93a45151b630c94b7f77637d173e6119fd41.1774256269.git.mchehab+huawei@kernel.org> --- tools/unittests/kdoc-test.yaml | 1548 +++++++++++++++++++++++++++++++- 1 file changed, 1546 insertions(+), 2 deletions(-) diff --git a/tools/unittests/kdoc-test.yaml b/tools/unittests/kdoc-test.yaml index b6e04f10ccdb..14d36daa1bba 100644 --- a/tools/unittests/kdoc-test.yaml +++ b/tools/unittests/kdoc-test.yaml @@ -22,7 +22,6 @@ tests: */ int func1(char *arg1) { return 0; }; - expected: - rst: | .. c:function:: int func1 (char *arg1) @@ -134,7 +133,6 @@ tests: always return 0. - # TODO: how to handle timestamps at .TH? man: | .TH "func2" 9 "February 2026" "" "Kernel API Manual" .SH NAME @@ -152,3 +150,1549 @@ tests: .SH "SEE ALSO" .PP Kernel file \fBfunc2.c\fR + +- name: doc_with_complex_table + description: Test if complex tables are handled + fname: mock.c + source: | + /** + * DOC: Supported input formats and encodings + * + * Depending on the Hardware configuration of the Controller IP, it supports + * a subset of the following input formats and encodings on its internal + * 48bit bus. + * + * +----------------------+----------------------------------+------------------------------+ + * | Format Name | Format Code | Encodings | + * +======================+==================================+==============================+ + * | RGB 4:4:4 8bit | ``MEDIA_BUS_FMT_RGB888_1X24`` | ``V4L2_YCBCR_ENC_DEFAULT`` | + * +----------------------+----------------------------------+------------------------------+ + * | RGB 4:4:4 10bits | ``MEDIA_BUS_FMT_RGB101010_1X30`` | ``V4L2_YCBCR_ENC_DEFAULT`` | + * +----------------------+----------------------------------+------------------------------+ + */ + expected: + - man: | + .TH "Supported input formats and encodings" 9 "March 2026" "" "Kernel API Manual" + .SH "Supported input formats and encodings" + Depending on the Hardware configuration of the Controller IP, it supports + a subset of the following input formats and encodings on its internal + 48bit bus. + .PP + + + .TS + box; + l l l. + \fBFormat Name\fP \fBFormat Code\fP \fBEncodings\fP + _ + RGB 4:4:4 8bit ``MEDIA_BUS_FMT_RGB888_1X24 V4L2_YCBCR_ENC_DEFAULT + RGB 4:4:4 10bits MEDIA_BUS_FMT_RGB101010_1X30 V4L2_YCBCR_ENC_DEFAULT`` + .TE + .SH "SEE ALSO" + .PP + Kernel file \fBmock.c\fR + + rst: |- + .. _Supported input formats and encodings: + **Supported input formats and encodings** + Depending on the Hardware configuration of the Controller IP, it supports + a subset of the following input formats and encodings on its internal + 48bit bus. + +----------------------+----------------------------------+------------------------------+ + | Format Name | Format Code | Encodings | + +======================+==================================+==============================+ + | RGB 4:4:4 8bit | ``MEDIA_BUS_FMT_RGB888_1X24`` | ``V4L2_YCBCR_ENC_DEFAULT`` | + +----------------------+----------------------------------+------------------------------+ + | RGB 4:4:4 10bits | ``MEDIA_BUS_FMT_RGB101010_1X30`` | ``V4L2_YCBCR_ENC_DEFAULT`` | + +----------------------+----------------------------------+------------------------------+ +- name: func_with_ascii_artwork + description: Test if ascii artwork is properly output + fname: mock.c + source: | + /** + * add_cxl_resources() - reflect CXL fixed memory windows in iomem_resource + * @cxl_res: A standalone resource tree where each CXL window is a sibling + * + * Walk each CXL window in @cxl_res and add it to iomem_resource potentially + * expanding its boundaries to ensure that any conflicting resources become + * children. If a window is expanded it may then conflict with a another window + * entry and require the window to be truncated or trimmed. Consider this + * situation:: + * + * |-- "CXL Window 0" --||----- "CXL Window 1" -----| + * |--------------- "System RAM" -------------| + * + * ...where platform firmware has established as System RAM resource across 2 + * windows, but has left some portion of window 1 for dynamic CXL region + * provisioning. In this case "Window 0" will span the entirety of the "System + * RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end + * of that "System RAM" resource. + */ + static int add_cxl_resources(struct resource *cxl_res); + expected: + - man: |- + .TH "add_cxl_resources" 9 "March 2026" "" "Kernel API Manual" + .SH NAME + add_cxl_resources \- reflect CXL fixed memory windows in iomem_resource + .SH SYNOPSIS + .B "int" add_cxl_resources + .BI "(struct resource *cxl_res " ");" + .SH ARGUMENTS + .IP "cxl_res" 12 + A standalone resource tree where each CXL window is a sibling + .SH "DESCRIPTION" + Walk each CXL window in \fIcxl_res\fP and add it to iomem_resource potentially + expanding its boundaries to ensure that any conflicting resources become + children. If a window is expanded it may then conflict with a another window + entry and require the window to be truncated or trimmed. Consider this + situation: + .nf + + |-- "CXL Window 0" --||----- "CXL Window 1" -----| + |--------------- "System RAM" -------------| + + + .fi + .PP + + \&...where platform firmware has established as System RAM resource across 2 + windows, but has left some portion of window 1 for dynamic CXL region + provisioning. In this case "Window 0" will span the entirety of the "System + RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end + of that "System RAM" resource. + .SH "SEE ALSO" + .PP + Kernel file \fBmock.c\fR + rst: | + .. c:function:: int add_cxl_resources (struct resource *cxl_res) + + reflect CXL fixed memory windows in iomem_resource + + .. container:: kernelindent + + **Parameters** + + ``struct resource *cxl_res`` + A standalone resource tree where each CXL window is a sibling + + **Description** + + Walk each CXL window in **cxl_res** and add it to iomem_resource potentially + expanding its boundaries to ensure that any conflicting resources become + children. If a window is expanded it may then conflict with a another window + entry and require the window to be truncated or trimmed. Consider this + situation:: + + |-- "CXL Window 0" --||----- "CXL Window 1" -----| + |--------------- "System RAM" -------------| + + ...where platform firmware has established as System RAM resource across 2 + windows, but has left some portion of window 1 for dynamic CXL region + provisioning. In this case "Window 0" will span the entirety of the "System + RAM" span, and "CXL Window 1" is truncated to the remaining tail past the end + of that "System RAM" resource. + +- name: simple_tables + description: Test formatting two simple tables + fname: mock.c + source: | + /** + * bitmap_onto - translate one bitmap relative to another + * @dst: resulting translated bitmap + * @orig: original untranslated bitmap + * @relmap: bitmap relative to which translated + * @bits: number of bits in each of these bitmaps + * + * =============== ============== ================= + * @orig tmp @dst + * 0 0 40 + * 1 1 41 + * =============== ============== ================= + * + * And: + * + * =============== ============== ================= + * @orig tmp @dst + * =============== ============== ================= + * 9 9 95 + * 10 0 40 [#f1]_ + * =============== ============== ================= + */ + void bitmap_onto(unsigned long *dst, const unsigned long *orig, + const unsigned long *relmap, unsigned int bits); + expected: + - man: | + .TH "bitmap_onto" 9 "March 2026" "" "Kernel API Manual" + .SH NAME + bitmap_onto \- translate one bitmap relative to another + .SH SYNOPSIS + .B "void" bitmap_onto + .BI "(unsigned long *dst " "," + .BI "const unsigned long *orig " "," + .BI "const unsigned long *relmap " "," + .BI "unsigned int bits " ");" + .SH ARGUMENTS + .IP "dst" 12 + resulting translated bitmap + .IP "orig" 12 + original untranslated bitmap + .IP "relmap" 12 + bitmap relative to which translated + .IP "bits" 12 + number of bits in each of these bitmaps + .SH "DESCRIPTION" + + .TS + box; + l l l. + \fIorig\fP tmp \fIdst\fP + 0 0 40 + 1 1 41 + .TE + .PP + + And: + .PP + + + .TS + box; + l l l. + \fIorig\fP tmp \fIdst\fP + .TE + 9 9 95 + 10 0 40 [#f1]_ + .SH "SEE ALSO" + .PP + Kernel file \fBmock.c\fR + + rst: | + .. c:function:: void bitmap_onto (unsigned long *dst, const unsigned long *orig, const unsigned long *relmap, unsigned int bits) + + translate one bitmap relative to another + + .. container:: kernelindent + + **Parameters** + + ``unsigned long *dst`` + resulting translated bitmap + + ``const unsigned long *orig`` + original untranslated bitmap + + ``const unsigned long *relmap`` + bitmap relative to which translated + + ``unsigned int bits`` + number of bits in each of these bitmaps + + **Description** + + =============== ============== ================= + **orig** tmp **dst** + 0 0 40 + 1 1 41 + =============== ============== ================= + + And: + + =============== ============== ================= + **orig** tmp **dst** + =============== ============== ================= + 9 9 95 + 10 0 40 [#f1]_ + =============== ============== ================= + +# +# Variable tests from Randy Dunlap's testset +# +- name: unsigned_long_var_on_uppercase + description: Test an unsigned long varaible in uppercase + fname: mock-vars.c + source: | + /** + * var ROOT_DEV - system root device + * + * @ROOT_DEV is either the successful root device or the root device + * that failed boot in the boot failure message. + */ + unsigned long ROOT_DEV; + expected: + - man: | + .TH "var ROOT_DEV" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + ROOT_DEV \- system root device + .SH SYNOPSIS + unsigned long ROOT_DEV; + .SH "Description" + \fIROOT_DEV\fP is either the successful root device or the root device + that failed boot in the boot failure message. + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: ROOT_DEV + + ``unsigned long ROOT_DEV;`` + + system root device + + **Description** + + **ROOT_DEV** is either the successful root device or the root device + that failed boot in the boot failure message. +- name: enum_var + description: Test an enum var with __read_mostly + fname: mock-vars.c + source: | + /** + * var system_state - system state used during boot or suspend/hibernate/resume + * + * @system_state can be used during boot to determine if it is safe to + * make certain calls to other parts of the kernel. It can also be used + * during suspend/hibernate or resume to determine the order of actions + * that need to be executed. The numerical values of system_state are + * sometimes used in numerical ordering tests, so the relative values + * must not be altered. + */ + enum system_states system_state __read_mostly; + expected: + - man: | + .TH "var system_state" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + system_state \- system state used during boot or suspend/hibernate/resume + .SH SYNOPSIS + enum system_states system_state __read_mostly; + .SH "Description" + \fIsystem_state\fP can be used during boot to determine if it is safe to + make certain calls to other parts of the kernel. It can also be used + during suspend/hibernate or resume to determine the order of actions + that need to be executed. The numerical values of system_state are + sometimes used in numerical ordering tests, so the relative values + must not be altered. + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: system_state + + ``enum system_states system_state __read_mostly;`` + + system state used during boot or suspend/hibernate/resume + + **Description** + + **system_state** can be used during boot to determine if it is safe to + make certain calls to other parts of the kernel. It can also be used + during suspend/hibernate or resume to determine the order of actions + that need to be executed. The numerical values of system_state are + sometimes used in numerical ordering tests, so the relative values + must not be altered. +- name: char_pointer_var + description: Test char * var with __ro_after_init + fname: mock-vars.c + source: | + /** + * var saved_command_line - kernel's command line, saved from use at + * any later time in the kernel. + */ + char *saved_command_line __ro_after_init; + expected: + - man: | + .TH "var saved_command_line" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + saved_command_line \- kernel's command line, saved from use at any later time in the kernel. + .SH SYNOPSIS + char *saved_command_line __ro_after_init; + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: saved_command_line + + ``char *saved_command_line __ro_after_init;`` + + kernel's command line, saved from use at any later time in the kernel. +- name: unsigned_long_with_default + description: Test an unsigned long var that is set to a default value + fname: mock-vars.c + source: | + /** + * var loop_per_jiffy - calculated loop count needed to consume one jiffy + * of time + */ + unsigned long loops_per_jiffy = (1<<12); + expected: + - man: | + .TH "var loops_per_jiffy" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + loops_per_jiffy \- calculated loop count needed to consume one jiffy of time + .SH SYNOPSIS + unsigned long loops_per_jiffy = (1<<12); + .SH "Initialization" + default: (1<<12) + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: loops_per_jiffy + + ``unsigned long loops_per_jiffy = (1<<12);`` + + calculated loop count needed to consume one jiffy of time + + **Initialization** + + default: ``(1<<12)`` +- name: unsigned_long + description: test a simple unsigned long variable. + fname: mock-vars.c + source: | + /** + * var preset_lpj - lpj (loops per jiffy) value set from kernel + * command line using "lpj=VALUE" + * + * See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. + */ + unsigned long preset_lpj; + expected: + - man: | + .TH "var preset_lpj" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + preset_lpj \- lpj (loops per jiffy) value set from kernel command line using "lpj=VALUE" + .SH SYNOPSIS + unsigned long preset_lpj; + .SH "Description" + See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: preset_lpj + + ``unsigned long preset_lpj;`` + + lpj (loops per jiffy) value set from kernel command line using "lpj=VALUE" + + **Description** + + See Documentation/admin-guide/kernel-parameters.txt ("lpj=") for details. +- name: char_array + description: test a char array variable + fname: mock-vars.c + source: | + /** + * var linux_proc_banner - text used from /proc/version file + * + * * first %s is sysname (e.g., "Linux") + * * second %s is release + * * third %s is version + */ + char linux_proc_banner[]; + expected: + - man: | + .TH "var linux_proc_banner" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + linux_proc_banner \- text used from /proc/version file + .SH SYNOPSIS + char linux_proc_banner[]; + .SH "Description" + .IP \[bu] + first s is sysname (e.g., "Linux") + .IP \[bu] + second s is release + .IP \[bu] + third s is version + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: linux_proc_banner + + ``char linux_proc_banner[];`` + + text used from /proc/version file + + **Description** + + * first ``s`` is sysname (e.g., "Linux") + * second ``s`` is release + * third ``s`` is version +- name: const_char_array + description: test a const char array variable + fname: mock-vars.c + source: | + /** + * var linux_banner - Linux boot banner, usually printed at boot time + */ + const char linux_banner[]; + expected: + - man: | + .TH "var linux_banner" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + linux_banner \- Linux boot banner, usually printed at boot time + .SH SYNOPSIS + const char linux_banner[]; + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: linux_banner + + ``const char linux_banner[];`` + + Linux boot banner, usually printed at boot time +- name: static_atomic64_t_var + description: test a static atomi64_t variable + fname: mock-vars.c + source: | + /** + * var diskseq - unique sequence number for block device instances + * + * Allows userspace to associate uevents to the lifetime of a device + */ + static atomic64_t diskseq; + expected: + - man: | + .TH "var diskseq" 9 "February 2026" "" "Kernel API Manual" + .SH NAME + diskseq \- unique sequence number for block device instances + .SH SYNOPSIS + static atomic64_t diskseq; + .SH "Description" + Allows userspace to associate uevents to the lifetime of a device + .SH "SEE ALSO" + .PP + Kernel file \fBmock-vars.c\fR + rst: | + .. c:macro:: diskseq + + ``static atomic64_t diskseq;`` + + unique sequence number for block device instances + + **Description** + + Allows userspace to associate uevents to the lifetime of a device +- name: unsigned_long_on_init + description: test an unsigned long var at "init" with a different timestamp. + fname: init/mock-vars.c + source: | + /** + * var rtnl_mutex - historical global lock for networking control operations. + * + * @rtnl_mutex is used to serialize rtnetlink requests + * and protect all kernel internal data structures related to networking. + * + * See Documentation/networking/netdevices.rst for details. + * Often known as the rtnl_lock, although rtnl_lock is a kernel function. + */ + unsigned long rtnl_mutex; + expected: + - man: | + .TH "var rtnl_mutex" 9 "February 2026" "init" "Kernel API Manual" + .SH NAME + rtnl_mutex \- historical global lock for networking control operations. + .SH SYNOPSIS + unsigned long rtnl_mutex; + .SH "Description" + \fIrtnl_mutex\fP is used to serialize rtnetlink requests + and protect all kernel internal data structures related to networking. + .PP + + See Documentation/networking/netdevices.rst for details. + Often known as the rtnl_lock, although rtnl_lock is a kernel function. + .SH "SEE ALSO" + .PP + Kernel file \fBinit/mock-vars.c\fR + rst: | + .. c:macro:: rtnl_mutex + + ``unsigned long rtnl_mutex;`` + + historical global lock for networking control operations. + + **Description** + + **rtnl_mutex** is used to serialize rtnetlink requests + and protect all kernel internal data structures related to networking. + + See Documentation/networking/netdevices.rst for details. + Often known as the rtnl_lock, although rtnl_lock is a kernel function. + + +- name: struct_kcov + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * struct kcov - kcov descriptor (one per opened debugfs file). + * State transitions of the descriptor: + * + * - initial state after open() + * - then there must be a single ioctl(KCOV_INIT_TRACE) call + * - then, mmap() call (several calls are allowed but not useful) + * - then, ioctl(KCOV_ENABLE, arg), where arg is + * KCOV_TRACE_PC - to trace only the PCs + * or + * KCOV_TRACE_CMP - to trace only the comparison operands + * - then, ioctl(KCOV_DISABLE) to disable the task. + * + * Enabling/disabling ioctls can be repeated (only one task a time allowed). + */ + struct kcov { + /** + * @refcount: Reference counter. We keep one for: + * - opened file descriptor + * - task with enabled coverage (we can't unwire it from another task) + * - each code section for remote coverage collection + */ + refcount_t refcount; + /** + * @lock: The lock protects mode, size, area and t. + */ + spinlock_t lock; + /** + * @mode: the kcov_mode + */ + enum kcov_mode mode __guarded_by(&lock); + /** + * @size: Size of arena (in long's). + */ + unsigned int size __guarded_by(&lock); + /** + * @area: Coverage buffer shared with user space. + */ + void *area __guarded_by(&lock); + /** + * @t: Task for which we collect coverage, or NULL. + */ + struct task_struct *t __guarded_by(&lock); + /** + * @remote: Collecting coverage from remote (background) threads. + */ + bool remote; + /** + * @remote_size: Size of remote area (in long's). + */ + unsigned int remote_size; + /** + * @sequence: Sequence is incremented each time kcov is reenabled, + * used by kcov_remote_stop(), see the comment there. + */ + int sequence; + }; + expected: + - man: | + .TH "struct kcov" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + struct kcov \- kcov descriptor (one per opened debugfs file). State transitions of the descriptor: + .SH SYNOPSIS + struct kcov { + .br + .BI " refcount_t refcount;" + .br + .BI " spinlock_t lock;" + .br + .BI " enum kcov_mode mode;" + .br + .BI " unsigned int size;" + .br + .BI " void *area;" + .br + .BI " struct task_struct *t;" + .br + .BI " bool remote;" + .br + .BI " unsigned int remote_size;" + .br + .BI " int sequence;" + .br + .BI " + }; + .br + + .SH Members + .IP "refcount" 12 + Reference counter. We keep one for: + .IP \[bu] + opened file descriptor + .IP \[bu] + task with enabled coverage (we can't unwire it from another task) + .IP \[bu] + each code section for remote coverage collection + .IP "lock" 12 + The lock protects mode, size, area and t. + .IP "mode" 12 + the kcov_mode + .IP "size" 12 + Size of arena (in long's). + .IP "area" 12 + Coverage buffer shared with user space. + .IP "t" 12 + Task for which we collect coverage, or NULL. + .IP "remote" 12 + Collecting coverage from remote (background) threads. + .IP "remote_size" 12 + Size of remote area (in long's). + .IP "sequence" 12 + Sequence is incremented each time kcov is reenabled, + used by \fBkcov_remote_stop\fP, see the comment there. + .SH "Description" + .IP \[bu] + initial state after \fBopen\fP + .IP \[bu] + then there must be a single ioctl(KCOV_INIT_TRACE) call + .IP \[bu] + then, \fBmmap\fP call (several calls are allowed but not useful) + .IP \[bu] + then, ioctl(KCOV_ENABLE, arg), where arg is + KCOV_TRACE_PC - to trace only the PCs + or + KCOV_TRACE_CMP - to trace only the comparison operands + .IP \[bu] + then, ioctl(KCOV_DISABLE) to disable the task. + .PP + + Enabling/disabling ioctls can be repeated (only one task a time allowed). + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:struct:: kcov + + kcov descriptor (one per opened debugfs file). State transitions of the descriptor: + + .. container:: kernelindent + + **Definition**:: + + struct kcov { + refcount_t refcount; + spinlock_t lock; + enum kcov_mode mode; + unsigned int size; + void *area; + struct task_struct *t; + bool remote; + unsigned int remote_size; + int sequence; + }; + + **Members** + + ``refcount`` + Reference counter. We keep one for: + - opened file descriptor + - task with enabled coverage (we can't unwire it from another task) + - each code section for remote coverage collection + + ``lock`` + The lock protects mode, size, area and t. + + ``mode`` + the kcov_mode + + ``size`` + Size of arena (in long's). + + ``area`` + Coverage buffer shared with user space. + + ``t`` + Task for which we collect coverage, or NULL. + + ``remote`` + Collecting coverage from remote (background) threads. + + ``remote_size`` + Size of remote area (in long's). + + ``sequence`` + Sequence is incremented each time kcov is reenabled, + used by kcov_remote_stop(), see the comment there. + + + **Description** + + - initial state after open() + - then there must be a single ioctl(KCOV_INIT_TRACE) call + - then, mmap() call (several calls are allowed but not useful) + - then, ioctl(KCOV_ENABLE, arg), where arg is + KCOV_TRACE_PC - to trace only the PCs + or + KCOV_TRACE_CMP - to trace only the comparison operands + - then, ioctl(KCOV_DISABLE) to disable the task. + + Enabling/disabling ioctls can be repeated (only one task a time allowed). + +- name: pool_offset + description: mock_tests/kdoc-drop-ctx-lock.c line 83 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * var pool_offset - Offset to the unused space in the currently used pool. + * + */ + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; + expected: + - man: | + .TH "var pool_offset" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + pool_offset \- Offset to the unused space in the currently used pool. + .SH SYNOPSIS + size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE; + .SH "Initialization" + default: DEPOT_POOL_SIZE + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:macro:: pool_offset + + ``size_t pool_offset __guarded_by(&pool_lock) = DEPOT_POOL_SIZE;`` + + Offset to the unused space in the currently used pool. + + **Initialization** + + default: ``DEPOT_POOL_SIZE`` +- name: free_stacks + description: mock_tests/kdoc-drop-ctx-lock.c line 88 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * var free_stacks - Freelist of stack records within stack_pools. + * + */ + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); + expected: + - man: | + .TH "var free_stacks" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + free_stacks \- Freelist of stack records within stack_pools. + .SH SYNOPSIS + __guarded_by(&pool_lock) LIST_HEAD(free_stacks); + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:macro:: free_stacks + + ``__guarded_by(&pool_lock) LIST_HEAD(free_stacks);`` + + Freelist of stack records within stack_pools. +- name: stack_pools + description: mock_tests/kdoc-drop-ctx-lock.c line 94 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * var stack_pools - Array of memory regions that store stack records. + * + */ + void **stack_pools __pt_guarded_by(&pool_lock); + expected: + - man: | + .TH "var stack_pools" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + stack_pools \- Array of memory regions that store stack records. + .SH SYNOPSIS + void **stack_pools __pt_guarded_by(&pool_lock); + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:macro:: stack_pools + + ``void **stack_pools __pt_guarded_by(&pool_lock);`` + + Array of memory regions that store stack records. +- name: prepare_report_consumer + description: mock_tests/kdoc-drop-ctx-lock.c line 103 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * prepare_report_consumer - prepare the report consumer + * @flags: flags + * @ai: not that AI + * @other_info: yes that + */ + bool prepare_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info) + __cond_acquires(true, &report_lock) + { + expected: + - man: | + .TH "prepare_report_consumer" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + prepare_report_consumer \- prepare the report consumer + .SH SYNOPSIS + .B "bool" prepare_report_consumer + .BI "(unsigned long *flags " "," + .BI "const struct access_info *ai " "," + .BI "struct other_info *other_info " ");" + .SH ARGUMENTS + .IP "flags" 12 + flags + .IP "ai" 12 + not that AI + .IP "other_info" 12 + yes that + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: bool prepare_report_consumer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) + + prepare the report consumer + + .. container:: kernelindent + + **Parameters** + + ``unsigned long *flags`` + flags + + ``const struct access_info *ai`` + not that AI + + ``struct other_info *other_info`` + yes that +- name: tcp_sigpool_start + description: mock_tests/kdoc-drop-ctx-lock.c line 117 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * tcp_sigpool_start - start a tcp message of @id, using @c + * @id: TCP message ID + * @c: the &tcp_sigpool to use + */ + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(0, RCU_BH) + { + expected: + - man: | + .TH "tcp_sigpool_start" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + tcp_sigpool_start \- start a tcp message of @id, using @c + .SH SYNOPSIS + .B "int" tcp_sigpool_start + .BI "(unsigned int id " "," + .BI "struct tcp_sigpool *c " ");" + .SH ARGUMENTS + .IP "id" 12 + TCP message ID + .IP "c" 12 + the \fItcp_sigpool\fP to use + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: int tcp_sigpool_start (unsigned int id, struct tcp_sigpool *c) + + start a tcp message of **id**, using **c** + + .. container:: kernelindent + + **Parameters** + + ``unsigned int id`` + TCP message ID + + ``struct tcp_sigpool *c`` + the :c:type:`tcp_sigpool` to use +- name: undo_report_consumer + description: mock_tests/kdoc-drop-ctx-lock.c line 129 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * undo_report_consumer - teardown a report consumer + * @flags: those flags + * @ai: not that AI + * @other_info: yes that + */ + bool undo_report_consumer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info) + __cond_releases(true, &report_lock) + { + expected: + - man: | + .TH "undo_report_consumer" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + undo_report_consumer \- teardown a report consumer + .SH SYNOPSIS + .B "bool" undo_report_consumer + .BI "(unsigned long *flags " "," + .BI "const struct access_info *ai " "," + .BI "struct other_info *other_info " ");" + .SH ARGUMENTS + .IP "flags" 12 + those flags + .IP "ai" 12 + not that AI + .IP "other_info" 12 + yes that + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: bool undo_report_consumer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) + + teardown a report consumer + + .. container:: kernelindent + + **Parameters** + + ``unsigned long *flags`` + those flags + + ``const struct access_info *ai`` + not that AI + + ``struct other_info *other_info`` + yes that +- name: debugfs_enter_cancellation + description: mock_tests/kdoc-drop-ctx-lock.c line 143 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * debugfs_enter_cancellation - begin a cancellation operation on @file + * @file: the target file + * @cancellation: the operation to execute + */ + void debugfs_enter_cancellation(struct file *file, + struct debugfs_cancellation *cancellation) __acquires(cancellation) + { } + expected: + - man: | + .TH "debugfs_enter_cancellation" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + debugfs_enter_cancellation \- begin a cancellation operation on @file + .SH SYNOPSIS + .B "void" debugfs_enter_cancellation + .BI "(struct file *file " "," + .BI "struct debugfs_cancellation *cancellation " ");" + .SH ARGUMENTS + .IP "file" 12 + the target file + .IP "cancellation" 12 + the operation to execute + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void debugfs_enter_cancellation (struct file *file, struct debugfs_cancellation *cancellation) + + begin a cancellation operation on **file** + + .. container:: kernelindent + + **Parameters** + + ``struct file *file`` + the target file + + ``struct debugfs_cancellation *cancellation`` + the operation to execute +- name: debugfs_leave_cancellation + description: mock_tests/kdoc-drop-ctx-lock.c line 152 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * debugfs_leave_cancellation - wrapup the cancellation operation on @file + * @file: the target file + * @cancellation: the operation to wrapup + */ + void debugfs_leave_cancellation(struct file *file, + struct debugfs_cancellation *cancellation) __releases(cancellation) + { } + expected: + - man: | + .TH "debugfs_leave_cancellation" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + debugfs_leave_cancellation \- wrapup the cancellation operation on @file + .SH SYNOPSIS + .B "void" debugfs_leave_cancellation + .BI "(struct file *file " "," + .BI "struct debugfs_cancellation *cancellation " ");" + .SH ARGUMENTS + .IP "file" 12 + the target file + .IP "cancellation" 12 + the operation to wrapup + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void debugfs_leave_cancellation (struct file *file, struct debugfs_cancellation *cancellation) + + wrapup the cancellation operation on **file** + + .. container:: kernelindent + + **Parameters** + + ``struct file *file`` + the target file + + ``struct debugfs_cancellation *cancellation`` + the operation to wrapup +- name: acpi_os_acquire_lock + description: mock_tests/kdoc-drop-ctx-lock.c line 161 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * acpi_os_acquire_lock - Acquire a spinlock. + * @lockp: pointer to the spinlock_t. + */ + acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) + __acquires(lockp) + { + expected: + - man: | + .TH "acpi_os_acquire_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + acpi_os_acquire_lock \- Acquire a spinlock. + .SH SYNOPSIS + .B "acpi_cpu_flags" acpi_os_acquire_lock + .BI "(acpi_spinlock lockp " ");" + .SH ARGUMENTS + .IP "lockp" 12 + pointer to the spinlock_t. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: acpi_cpu_flags acpi_os_acquire_lock (acpi_spinlock lockp) + + Acquire a spinlock. + + .. container:: kernelindent + + **Parameters** + + ``acpi_spinlock lockp`` + pointer to the spinlock_t. +- name: acpi_os_release_lock + description: mock_tests/kdoc-drop-ctx-lock.c line 172 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * acpi_os_release_lock - Release a spinlock. + * @lockp: pointer to the spinlock_t. + * @not_used: these flags are not used. + */ + void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags not_used) + __releases(lockp) + { + expected: + - man: | + .TH "acpi_os_release_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + acpi_os_release_lock \- Release a spinlock. + .SH SYNOPSIS + .B "void" acpi_os_release_lock + .BI "(acpi_spinlock lockp " "," + .BI "acpi_cpu_flags not_used " ");" + .SH ARGUMENTS + .IP "lockp" 12 + pointer to the spinlock_t. + .IP "not_used" 12 + these flags are not used. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void acpi_os_release_lock (acpi_spinlock lockp, acpi_cpu_flags not_used) + + Release a spinlock. + + .. container:: kernelindent + + **Parameters** + + ``acpi_spinlock lockp`` + pointer to the spinlock_t. + + ``acpi_cpu_flags not_used`` + these flags are not used. +- name: tx + description: mock_tests/kdoc-drop-ctx-lock.c line 183 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * tx - transmit message ID @id + * @id: message ID to transmit + */ + int tx(int id) __must_hold(&txlock) + { + expected: + - man: | + .TH "tx" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + tx \- transmit message ID @id + .SH SYNOPSIS + .B "int" tx + .BI "(int id " ");" + .SH ARGUMENTS + .IP "id" 12 + message ID to transmit + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: int tx (int id) + + transmit message ID **id** + + .. container:: kernelindent + + **Parameters** + + ``int id`` + message ID to transmit +- name: contend_for_bm + description: mock_tests/kdoc-drop-ctx-lock.c line 192 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * contend_for_bm - try to become the bus master + * @card: the &fw_card (describes the bus) + */ + enum bm_contention_outcome contend_for_bm(struct fw_card *card) + __must_hold(&card->lock) + { + expected: + - man: | + .TH "contend_for_bm" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + contend_for_bm \- try to become the bus master + .SH SYNOPSIS + .B "enum bm_contention_outcome" contend_for_bm + .BI "(struct fw_card *card " ");" + .SH ARGUMENTS + .IP "card" 12 + the \fIfw_card\fP (describes the bus) + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: enum bm_contention_outcome contend_for_bm (struct fw_card *card) + + try to become the bus master + + .. container:: kernelindent + + **Parameters** + + ``struct fw_card *card`` + the :c:type:`fw_card` (describes the bus) +- name: prepare_report_producer + description: mock_tests/kdoc-drop-ctx-lock.c line 202 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * prepare_report_producer - prepare the report producer + * @flags: still flags + * @ai: some AI + * @other_info: Populate @other_info; requires that the provided + * @other_info not in use. + */ + void prepare_report_producer(unsigned long *flags, + const struct access_info *ai, + struct other_info *other_info) + __must_not_hold(&report_lock) + { } + expected: + - man: | + .TH "prepare_report_producer" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + prepare_report_producer \- prepare the report producer + .SH SYNOPSIS + .B "void" prepare_report_producer + .BI "(unsigned long *flags " "," + .BI "const struct access_info *ai " "," + .BI "struct other_info *other_info " ");" + .SH ARGUMENTS + .IP "flags" 12 + still flags + .IP "ai" 12 + some AI + .IP "other_info" 12 + Populate \fIother_info\fP; requires that the provided + \fIother_info\fP not in use. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void prepare_report_producer (unsigned long *flags, const struct access_info *ai, struct other_info *other_info) + + prepare the report producer + + .. container:: kernelindent + + **Parameters** + + ``unsigned long *flags`` + still flags + + ``const struct access_info *ai`` + some AI + + ``struct other_info *other_info`` + Populate **other_info**; requires that the provided + **other_info** not in use. +- name: crypto_alg_lookup + description: mock_tests/kdoc-drop-ctx-lock.c line 215 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * __crypto_alg_lookup() - lookup the algorithm by name/type/mask + * @name: name to search for + * @type: type to search for + * @mask: mask to match + */ + struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, + u32 mask) + __must_hold_shared(&crypto_alg_sem) + { + expected: + - man: | + .TH "__crypto_alg_lookup" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + __crypto_alg_lookup \- lookup the algorithm by name/type/mask + .SH SYNOPSIS + .B "struct crypto_alg *" __crypto_alg_lookup + .BI "(const char *name " "," + .BI "u32 type " "," + .BI "u32 mask " ");" + .SH ARGUMENTS + .IP "name" 12 + name to search for + .IP "type" 12 + type to search for + .IP "mask" 12 + mask to match + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: struct crypto_alg * __crypto_alg_lookup (const char *name, u32 type, u32 mask) + + lookup the algorithm by name/type/mask + + .. container:: kernelindent + + **Parameters** + + ``const char *name`` + name to search for + + ``u32 type`` + type to search for + + ``u32 mask`` + mask to match +- name: down_read_trylock + description: mock_tests/kdoc-drop-ctx-lock.c line 228 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * down_read_trylock - trylock for reading + * @sem: the semaphore to try to lock + * + * Returns: 1 if successful, 0 if contention + */ + extern int down_read_trylock(struct rw_semaphore *sem) __cond_acquires_shared(true, sem); + expected: + - man: | + .TH "down_read_trylock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + down_read_trylock \- trylock for reading + .SH SYNOPSIS + .B "int" down_read_trylock + .BI "(struct rw_semaphore *sem " ");" + .SH ARGUMENTS + .IP "sem" 12 + the semaphore to try to lock + .SH "RETURN" + 1 if successful, 0 if contention + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: int down_read_trylock (struct rw_semaphore *sem) + + trylock for reading + + .. container:: kernelindent + + **Parameters** + + ``struct rw_semaphore *sem`` + the semaphore to try to lock + + **Return** + + 1 if successful, 0 if contention +- name: tomoyo_read_lock + description: mock_tests/kdoc-drop-ctx-lock.c line 236 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * tomoyo_read_lock - Take lock for protecting policy. + * + * Returns: index number for tomoyo_read_unlock(). + */ + int tomoyo_read_lock(void) + __acquires_shared(&tomoyo_ss) + { + expected: + - man: | + .TH "tomoyo_read_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + tomoyo_read_lock \- Take lock for protecting policy. + .SH SYNOPSIS + .B "int" tomoyo_read_lock + .BI "(void " ");" + .SH ARGUMENTS + .IP "void" 12 + no arguments + .SH "RETURN" + index number for \fBtomoyo_read_unlock\fP. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: int tomoyo_read_lock (void) + + Take lock for protecting policy. + + .. container:: kernelindent + + **Parameters** + + ``void`` + no arguments + + **Return** + + index number for tomoyo_read_unlock(). +- name: tomoyo_read_unlock + description: mock_tests/kdoc-drop-ctx-lock.c line 247 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * tomoyo_read_unlock - Release lock for protecting policy. + * + * @idx: Index number returned by tomoyo_read_lock(). + */ + void tomoyo_read_unlock(int idx) + __releases_shared(&tomoyo_ss) + { } + expected: + - man: | + .TH "tomoyo_read_unlock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + tomoyo_read_unlock \- Release lock for protecting policy. + .SH SYNOPSIS + .B "void" tomoyo_read_unlock + .BI "(int idx " ");" + .SH ARGUMENTS + .IP "idx" 12 + Index number returned by \fBtomoyo_read_lock\fP. + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void tomoyo_read_unlock (int idx) + + Release lock for protecting policy. + + .. container:: kernelindent + + **Parameters** + + ``int idx`` + Index number returned by tomoyo_read_lock(). +- name: c_stop + description: mock_tests/kdoc-drop-ctx-lock.c line 256 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * c_stop - stop the seq_file iteration + * @m: the &struct seq_file + * @p: handle + */ + void c_stop(struct seq_file *m, void *p) + __releases_shared(&crypto_alg_sem) + { } + expected: + - man: | + .TH "c_stop" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + c_stop \- stop the seq_file iteration + .SH SYNOPSIS + .B "void" c_stop + .BI "(struct seq_file *m " "," + .BI "void *p " ");" + .SH ARGUMENTS + .IP "m" 12 + the \fIstruct seq_file\fP + .IP "p" 12 + handle + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void c_stop (struct seq_file *m, void *p) + + stop the seq_file iteration + + .. container:: kernelindent + + **Parameters** + + ``struct seq_file *m`` + the :c:type:`struct seq_file ` + + ``void *p`` + handle +- name: spin_lock + description: mock_tests/kdoc-drop-ctx-lock.c line 265 + fname: mock_tests/kdoc-drop-ctx-lock.c + source: | + /** + * spin_lock - spin until the @lock is acquired + * @lock: the spinlock + */ + void spin_lock(spinlock_t *lock) + __acquires(lock) __no_context_analysis + { } + expected: + - man: | + .TH "spin_lock" 9 "February 2026" "mock_tests" "Kernel API Manual" + .SH NAME + spin_lock \- spin until the @lock is acquired + .SH SYNOPSIS + .B "void" spin_lock + .BI "(spinlock_t *lock " ");" + .SH ARGUMENTS + .IP "lock" 12 + the spinlock + .SH "SEE ALSO" + .PP + Kernel file \fBmock_tests/kdoc-drop-ctx-lock.c\fR + rst: | + .. c:function:: void spin_lock (spinlock_t *lock) + + spin until the **lock** is acquired + + .. container:: kernelindent + + **Parameters** + + ``spinlock_t *lock`` + the spinlock From 8326e4a21838593fe67b5d79ba6d0dc8e962ebb9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:49 +0100 Subject: [PATCH 125/162] docs: kdoc_output: fix handling of simple tables Fix check for simple table delimiters. ReST simple tables use "=" instead of "-". I ended testing it with a table modified from a complex one, using "--- --- ---", instead of searching for a real Kernel example. Only noticed when adding an unit test and seek for an actual example from kernel-doc markups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_output.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 1b54117dbe19..2bfcd356654b 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -846,14 +846,14 @@ class ManFormat(OutputFormat): colspec_row = None pos = [] - for m in KernRe(r'\-+').finditer(lines[i]): + for m in KernRe(r'\=+').finditer(lines[i]): pos.append((m.start(), m.end() - 1)) i += 1 while i < len(lines): line = lines[i] - if KernRe(r"^\s*[\-]+[ \t\-]+$").match(line): + if KernRe(r"^\s*[\=]+[ \t\=]+$").match(line): i += 1 break @@ -969,7 +969,7 @@ class ManFormat(OutputFormat): self.data += text continue - if KernRe(r"^\-+[ \t]\-[ \t\-]+$").match(line): + if KernRe(r"^\=+[ \t]\=[ \t\=]+$").match(line): i, text = self.simple_table(lines, i) self.data += text continue From 99ec67a9984fdf38c7ed78695aeb1b99cfee5b50 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:50 +0100 Subject: [PATCH 126/162] docs: kdoc: better handle source when producing YAML output The current logic was storing symbols source code on a list, not linked to the actual KdocItem. While this works fine when kernel-doc markups are OK, on places where there is a "/**" without a valid kernel-doc markup, it ends that the 1:1 match between source code and KdocItem doesn't happen, causing problems to generate the YAML output. Fix it by storing the source code directly into the KdocItem structure. This shouldn't affect performance or memory footprint, except when --yaml option is used. While here, add a __repr__() function for KdocItem, as it helps debugging it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <77902dafabb5c3250486aa2dc1568d5fafa95c5b.1774256269.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_files.py | 8 +- tools/lib/python/kdoc/kdoc_item.py | 6 +- tools/lib/python/kdoc/kdoc_parser.py | 100 ++++++++++++------------ tools/lib/python/kdoc/kdoc_yaml_file.py | 28 +++---- tools/unittests/test_kdoc_parser.py | 9 +++ 5 files changed, 79 insertions(+), 72 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 5a299ed44d62..2428cfc4e843 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -203,10 +203,6 @@ class KernelFiles(): self.results[fname] = entries - source = doc.get_source() - if source: - self.source[fname] = source - def process_export_file(self, fname): """ Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file. @@ -294,7 +290,6 @@ class KernelFiles(): self.errors = 0 self.results = {} - self.source = {} self.files = set() self.export_files = set() @@ -364,8 +359,7 @@ class KernelFiles(): function_table, enable_lineno, no_doc_sections) - self.test_file.output_symbols(fname, symbols, - self.source.get(fname)) + self.test_file.output_symbols(fname, symbols) continue diff --git a/tools/lib/python/kdoc/kdoc_item.py b/tools/lib/python/kdoc/kdoc_item.py index fe08cac861c2..a7aa6e1e4c1c 100644 --- a/tools/lib/python/kdoc/kdoc_item.py +++ b/tools/lib/python/kdoc/kdoc_item.py @@ -14,7 +14,8 @@ class KdocItem: then pass into the output modules. """ - def __init__(self, name, fname, type, start_line, **other_stuff): + def __init__(self, name, fname, type, start_line, + **other_stuff): self.name = name self.fname = fname self.type = type @@ -60,6 +61,9 @@ class KdocItem: def __getitem__(self, key): return self.get(key) + def __repr__(self): + return f"KdocItem({self.name}, {self.fname}, {self.type}, {self.declaration_start_line})" + @classmethod def from_dict(cls, d): """Create a KdocItem from a plain dict.""" diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py index a10e64589d76..74af7ae47aa4 100644 --- a/tools/lib/python/kdoc/kdoc_parser.py +++ b/tools/lib/python/kdoc/kdoc_parser.py @@ -265,9 +265,6 @@ class KernelDoc: # Place all potential outputs into an array self.entries = [] - # When store_src is true, the kernel-doc source content is stored here - self.source = None - # # We need Python 3.7 for its "dicts remember the insertion # order" guarantee @@ -720,13 +717,14 @@ class KernelDoc: return declaration - def dump_struct(self, ln, proto): + def dump_struct(self, ln, proto, source): """ Store an entry for a ``struct`` or ``union`` """ # # Do the basic parse to get the pieces of the declaration. # + source = source proto = trim_private_members(proto) struct_parts = self.split_struct_proto(proto) if not struct_parts: @@ -756,10 +754,11 @@ class KernelDoc: declaration_name) self.check_sections(ln, declaration_name, decl_type) self.output_declaration(decl_type, declaration_name, + source=source, definition=self.format_struct_decl(declaration), purpose=self.entry.declaration_purpose) - def dump_enum(self, ln, proto): + def dump_enum(self, ln, proto, source): """ Store an ``enum`` inside self.entries array. """ @@ -767,6 +766,7 @@ class KernelDoc: # Strip preprocessor directives. Note that this depends on the # trailing semicolon we added in process_proto_type(). # + source = source proto = trim_private_members(proto) proto = KernRe(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags=re.S).sub('', proto) # @@ -831,9 +831,10 @@ class KernelDoc: f"Excess enum value '@{k}' description in '{declaration_name}'") self.output_declaration('enum', declaration_name, + source=source, purpose=self.entry.declaration_purpose) - def dump_var(self, ln, proto): + def dump_var(self, ln, proto, source): """ Store variables that are part of kAPI. """ @@ -846,6 +847,7 @@ class KernelDoc: # # Store the full prototype before modifying it # + source = source full_proto = proto declaration_name = None @@ -895,32 +897,34 @@ class KernelDoc: default_val = default_val.lstrip("=").strip() self.output_declaration("var", declaration_name, + source=source, full_proto=full_proto, default_val=default_val, purpose=self.entry.declaration_purpose) - def dump_declaration(self, ln, prototype): + def dump_declaration(self, ln, prototype, source): """ Store a data declaration inside self.entries array. """ if self.entry.decl_type == "enum": - self.dump_enum(ln, prototype) + self.dump_enum(ln, prototype, source) elif self.entry.decl_type == "typedef": - self.dump_typedef(ln, prototype) + self.dump_typedef(ln, prototype, source) elif self.entry.decl_type in ["union", "struct"]: - self.dump_struct(ln, prototype) + self.dump_struct(ln, prototype, source) elif self.entry.decl_type == "var": - self.dump_var(ln, prototype) + self.dump_var(ln, prototype, source) else: # This would be a bug self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}') - def dump_function(self, ln, prototype): + def dump_function(self, ln, prototype, source): """ Store a function or function macro inside self.entries array. """ + source = source found = func_macro = False return_type = '' decl_type = 'function' @@ -1013,13 +1017,14 @@ class KernelDoc: # Store the result. # self.output_declaration(decl_type, declaration_name, + source=source, typedef=('typedef' in return_type), functiontype=return_type, purpose=self.entry.declaration_purpose, func_macro=func_macro) - def dump_typedef(self, ln, proto): + def dump_typedef(self, ln, proto, source): """ Store a ``typedef`` inside self.entries array. """ @@ -1030,6 +1035,8 @@ class KernelDoc: typedef_ident = r'\*?\s*(\w\S+)\s*' typedef_args = r'\s*\((.*)\);' + source = source + typedef1 = KernRe(typedef_type + r'\(' + typedef_ident + r'\)' + typedef_args) typedef2 = KernRe(typedef_type + typedef_ident + typedef_args) @@ -1050,6 +1057,7 @@ class KernelDoc: self.create_parameter_list(ln, 'function', args, ',', declaration_name) self.output_declaration('function', declaration_name, + source=source, typedef=True, functiontype=return_type, purpose=self.entry.declaration_purpose) @@ -1067,6 +1075,7 @@ class KernelDoc: return self.output_declaration('typedef', declaration_name, + source=source, purpose=self.entry.declaration_purpose) return @@ -1104,7 +1113,7 @@ class KernelDoc: function_set.add(symbol) return True - def process_normal(self, ln, line): + def process_normal(self, ln, line, source): """ STATE_NORMAL: looking for the ``/**`` to begin everything. """ @@ -1118,7 +1127,7 @@ class KernelDoc: # next line is always the function name self.state = state.NAME - def process_name(self, ln, line): + def process_name(self, ln, line, source): """ STATE_NAME: Looking for the "name - description" line """ @@ -1251,7 +1260,7 @@ class KernelDoc: return False - def process_decl(self, ln, line): + def process_decl(self, ln, line, source): """ STATE_DECLARATION: We've seen the beginning of a declaration. """ @@ -1280,7 +1289,7 @@ class KernelDoc: self.emit_msg(ln, f"bad line: {line}") - def process_special(self, ln, line): + def process_special(self, ln, line, source): """ STATE_SPECIAL_SECTION: a section ending with a blank line. """ @@ -1331,7 +1340,7 @@ class KernelDoc: # Unknown line, ignore self.emit_msg(ln, f"bad line: {line}") - def process_body(self, ln, line): + def process_body(self, ln, line, source): """ STATE_BODY: the bulk of a kerneldoc comment. """ @@ -1345,7 +1354,7 @@ class KernelDoc: # Unknown line, ignore self.emit_msg(ln, f"bad line: {line}") - def process_inline_name(self, ln, line): + def process_inline_name(self, ln, line, source): """STATE_INLINE_NAME: beginning of docbook comments within a prototype.""" if doc_inline_sect.search(line): @@ -1363,10 +1372,10 @@ class KernelDoc: # Don't let it add partial comments at the code, as breaks the # logic meant to remove comments from prototypes. # - self.process_proto_type(ln, "/**\n" + line) + self.process_proto_type(ln, "/**\n" + line, source) # else ... ?? - def process_inline_text(self, ln, line): + def process_inline_text(self, ln, line, source): """STATE_INLINE_TEXT: docbook comments within a prototype.""" if doc_inline_end.search(line): @@ -1452,7 +1461,7 @@ class KernelDoc: return proto - def process_proto_function(self, ln, line): + def process_proto_function(self, ln, line, source): """Ancillary routine to process a function prototype.""" # strip C99-style comments to end of line @@ -1494,10 +1503,10 @@ class KernelDoc: # # ... and we're done # - self.dump_function(ln, self.entry.prototype) + self.dump_function(ln, self.entry.prototype, source) self.reset_state(ln) - def process_proto_type(self, ln, line): + def process_proto_type(self, ln, line, source): """ Ancillary routine to process a type. """ @@ -1527,7 +1536,7 @@ class KernelDoc: elif chunk == '}': self.entry.brcount -= 1 elif chunk == ';' and self.entry.brcount <= 0: - self.dump_declaration(ln, self.entry.prototype) + self.dump_declaration(ln, self.entry.prototype, source) self.reset_state(ln) return # @@ -1536,7 +1545,7 @@ class KernelDoc: # self.entry.prototype += ' ' - def process_proto(self, ln, line): + def process_proto(self, ln, line, source): """STATE_PROTO: reading a function/whatever prototype.""" if doc_inline_oneline.search(line): @@ -1548,17 +1557,18 @@ class KernelDoc: self.state = state.INLINE_NAME elif self.entry.decl_type == 'function': - self.process_proto_function(ln, line) + self.process_proto_function(ln, line, source) else: - self.process_proto_type(ln, line) + self.process_proto_type(ln, line, source) - def process_docblock(self, ln, line): + def process_docblock(self, ln, line, source): """STATE_DOCBLOCK: within a ``DOC:`` block.""" if doc_end.search(line): self.dump_section() - self.output_declaration("doc", self.entry.identifier) + self.output_declaration("doc", self.entry.identifier, + source=source) self.reset_state(ln) elif doc_content.search(line): @@ -1596,15 +1606,6 @@ class KernelDoc: state.DOCBLOCK: process_docblock, } - def get_source(self): - """ - Return the file content of the lines handled by kernel-doc at the - latest parse_kdoc() run. - - Returns none if KernelDoc() was not initialized with store_src, - """ - return self.source - def parse_kdoc(self): """ Open and process each line of a C source file. @@ -1618,8 +1619,8 @@ class KernelDoc: prev = "" prev_ln = None export_table = set() - self.source = [] self.state = state.NORMAL + source = "" try: with open(self.fname, "r", encoding="utf8", @@ -1646,7 +1647,11 @@ class KernelDoc: ln, state.name[self.state], line) - prev_state = self.state + if self.store_src: + if source and self.state == state.NORMAL: + source = "" + elif self.state != state.NORMAL: + source += line + "\n" # This is an optimization over the original script. # There, when export_file was used for the same file, @@ -1655,16 +1660,11 @@ class KernelDoc: # if (self.state != state.NORMAL) or \ not self.process_export(export_table, line): + prev_state = self.state # Hand this line to the appropriate state handler - self.state_actions[self.state](self, ln, line) - - if self.store_src and prev_state != self.state or self.state != state.NORMAL: - if self.state == state.NAME: - # A "/**" was detected. Add a new source element - self.source.append({"ln": ln, "data": line + "\n"}) - else: - # Append to the existing one - self.source[-1]["data"] += line + "\n" + self.state_actions[self.state](self, ln, line, source) + if prev_state == state.NORMAL and self.state != state.NORMAL: + source += line + "\n" self.emit_unused_warnings() diff --git a/tools/lib/python/kdoc/kdoc_yaml_file.py b/tools/lib/python/kdoc/kdoc_yaml_file.py index 18737abb1176..1e2ae7c59d70 100644 --- a/tools/lib/python/kdoc/kdoc_yaml_file.py +++ b/tools/lib/python/kdoc/kdoc_yaml_file.py @@ -85,7 +85,7 @@ class KDocTestFile(): return d - def output_symbols(self, fname, symbols, source): + def output_symbols(self, fname, symbols): """ Store source, symbols and output strings at self.tests. """ @@ -96,16 +96,10 @@ class KDocTestFile(): kdoc_item = [] expected = [] - if not symbols and not source: - return - - if not source or len(symbols) != len(source): - print(f"Warning: lengths are different. Ignoring {fname}") - - # Folding without line numbers is too hard. - # The right thing to do here to proceed would be to delete - # not-handled source blocks, as len(source) should be bigger - # than len(symbols) + # + # Source code didn't produce any symbol + # + if not symbols: return base_name = "test_" + fname.replace(".", "_").replace("/", "_") @@ -115,9 +109,15 @@ class KDocTestFile(): for i in range(0, len(symbols)): arg = symbols[i] - if "KdocItem" in self.yaml_content: + source = arg.get("source", "") + + if arg and "KdocItem" in self.yaml_content: msg = self.get_kdoc_item(arg) + other_stuff = msg.get("other_stuff", {}) + if "source" in other_stuff: + del other_stuff["source"] + expected_dict["kdoc_item"] = msg for out_style in self.out_style: @@ -132,9 +132,9 @@ class KDocTestFile(): test = { "name": name, - "description": f"{fname} line {source[i]["ln"]}", + "description": f"{fname} line {arg.declaration_start_line}", "fname": fname, - "source": source[i]["data"], + "source": source, "expected": [expected_dict] } diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py index f2250ef192ce..c4a76ed13dbc 100755 --- a/tools/unittests/test_kdoc_parser.py +++ b/tools/unittests/test_kdoc_parser.py @@ -167,7 +167,16 @@ class GenerateKdocItem(unittest.TestCase): self.assertIsInstance(entry, KdocItem) d = vars(entry) + + other_stuff = d.get("other_stuff", {}) + if "source" in other_stuff: + del other_stuff["source"] + for key, value in expected.items(): + if key == "other_stuff": + if "source" in value: + del value["source"] + result = clean_whitespc(d[key], relax_whitespace) value = clean_whitespc(value, relax_whitespace) From e786fab2cfcc9ab65adf35d2eab4ca94abe1955f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:51 +0100 Subject: [PATCH 127/162] docs: kdoc_yaml_file: use a better name for the tests Instead of always using a name with a number on it, use the name of the object directly whenever possible. When the name is already used, append a number prefix at the end. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: --- tools/lib/python/kdoc/kdoc_yaml_file.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/lib/python/kdoc/kdoc_yaml_file.py b/tools/lib/python/kdoc/kdoc_yaml_file.py index 1e2ae7c59d70..0be020d50df0 100644 --- a/tools/lib/python/kdoc/kdoc_yaml_file.py +++ b/tools/lib/python/kdoc/kdoc_yaml_file.py @@ -25,6 +25,7 @@ class KDocTestFile(): self.config = config self.test_file = os.path.expanduser(yaml_file) self.yaml_content = yaml_content + self.test_names = set() self.tests = [] @@ -102,13 +103,10 @@ class KDocTestFile(): if not symbols: return - base_name = "test_" + fname.replace(".", "_").replace("/", "_") expected_dict = {} start_line=1 - for i in range(0, len(symbols)): - arg = symbols[i] - + for arg in symbols: source = arg.get("source", "") if arg and "KdocItem" in self.yaml_content: @@ -120,6 +118,21 @@ class KDocTestFile(): expected_dict["kdoc_item"] = msg + base_name = arg.name + if not base_name: + base_name = fname + base_name = base_name.lower().replace(".", "_").replace("/", "_") + + + # Don't add duplicated names + i = 0 + name = base_name + while name in self.test_names: + i += 1 + name = f"{base_name}_{i:03d}" + + self.test_names.add(name) + for out_style in self.out_style: if isinstance(out_style, ManFormat): key = "man" @@ -128,8 +141,6 @@ class KDocTestFile(): expected_dict[key]= out_style.output_symbols(fname, [arg]).strip() - name = f"{base_name}_{i:03d}" - test = { "name": name, "description": f"{fname} line {arg.declaration_start_line}", From 9c3911812b4a719623ea7502b419929eb01b2fc2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:52 +0100 Subject: [PATCH 128/162] docs: kdoc_output: raise an error if full_proto not available for var This is mandatory, but if it is missing, we need to know what symbol had problems. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <0c3d9dd25889784b999efdb354ade48264c0e03c.1774256269.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/kdoc_output.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/kdoc_output.py b/tools/lib/python/kdoc/kdoc_output.py index 2bfcd356654b..de107ab4a281 100644 --- a/tools/lib/python/kdoc/kdoc_output.py +++ b/tools/lib/python/kdoc/kdoc_output.py @@ -513,7 +513,9 @@ class RestFormat(OutputFormat): def out_var(self, fname, name, args): oldprefix = self.lineprefix ln = args.declaration_start_line - full_proto = args.other_stuff["full_proto"] + full_proto = args.other_stuff.get("full_proto") + if not full_proto: + raise KeyError(f"Can't find full proto for {name} variable") self.lineprefix = " " From 2ca0b54dca438edb0f6b0eec7913d3cab60ddebf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 23 Mar 2026 10:10:53 +0100 Subject: [PATCH 129/162] docs: c_lex.py: store logger on its data By having the logger stored there, any code using CTokenizer can log messages there. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <467979dc18149e4b2a7113c178e0cb07919632f2.1774256269.git.mchehab+huawei@kernel.org> --- tools/lib/python/kdoc/c_lex.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/lib/python/kdoc/c_lex.py b/tools/lib/python/kdoc/c_lex.py index e01b154f458e..cb95f5172448 100644 --- a/tools/lib/python/kdoc/c_lex.py +++ b/tools/lib/python/kdoc/c_lex.py @@ -177,7 +177,7 @@ class CTokenizer(): # This class is inspired and follows the basic concepts of: # https://docs.python.org/3/library/re.html#writing-a-tokenizer - def __init__(self, source=None, log=None): + def __init__(self, source=None): """ Create a regular expression to handle RE_SCANNER_LIST. @@ -188,6 +188,12 @@ class CTokenizer(): when matching a code via RE_SCANNER. """ + # + # Store logger to allow parser classes to re-use it + # + global log + self.log = log + self.tokens = [] if not source: From 1329cc0b8d28454c3e87a28c62a4426cc53ba254 Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Mon, 23 Mar 2026 14:11:31 -0300 Subject: [PATCH 130/162] docs: pt_BR: Add translation for process/conclave.rst Translate the Linux kernel project continuity documentation (conclave.rst) into Portuguese (pt_BR). Also, update the main pt_BR index to include the link to the new translation. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260323171133.88074-2-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../translations/pt_BR/process/conclave.rst | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 Documentation/translations/pt_BR/process/conclave.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index a89837aefc3e..efe6a4a3fef1 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -69,6 +69,7 @@ kernel e sobre como ver seu trabalho integrado. Introdução Como começar Requisitos mínimos + Conclave (Continuidade do projeto) Manuais dos mantenedores Processo do subsistema de rede (netdev) Processo do subsistema SoC diff --git a/Documentation/translations/pt_BR/process/conclave.rst b/Documentation/translations/pt_BR/process/conclave.rst new file mode 100644 index 000000000000..9071b5a39303 --- /dev/null +++ b/Documentation/translations/pt_BR/process/conclave.rst @@ -0,0 +1,40 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Continuidade do projeto do kernel Linux +======================================= + +O projeto de desenvolvimento do kernel Linux é amplamente distribuído, com mais de +100 mantenedores, cada um trabalhando para manter as mudanças fluindo através de +seus próprios repositórios. A etapa final, no entanto, é centralizada, onde as +mudanças são puxadas para o repositório mainline. Isso é normalmente feito por +Linus Torvalds mas, como foi demonstrado pelo lançamento da versão 4.19 em 2018, +existem outros que podem realizar esse trabalho quando surge a necessidade. + +Caso os mantenedores desse repositório se tornem indispostos ou incapazes de +realizar esse trabalho daqui em diante (incluindo a facilitação de uma transição), +o projeto precisará encontrar um ou mais substitutos sem demora. O processo pelo +qual isso será feito está listado abaixo. O $ORGANIZER é o último organizador do +Maintainer Summit ou o atual presidente do Conselho Consultivo Técnico (TAB) da +Linux Foundation (LF) como reserva. + +- Em até 72 horas, o $ORGANIZER abrirá uma discussão com os convidados do + Maintainer Summit concluído mais recentemente. Uma reunião desses convidados e + do TAB, seja online ou presencial, será agendada o mais rápido possível de uma + forma que maximize o número de pessoas que possam participar. + +- Se não houver ocorrido um Maintainer Summit nos últimos 15 meses, o conjunto de + convidados para esta reunião será determinado pelo TAB. + +- Os convidados para esta reunião podem trazer outros mantenedores conforme + necessário. + +- Esta reunião, presidida pelo $ORGANIZER, considerará opções para a gestão + contínua do repositório de nível superior do kernel, de forma consistente com + a expectativa de maximizar a saúde a longo prazo do projeto e de sua comunidade. + +- Em até duas semanas, um representante deste grupo comunicará à comunidade em + geral, utilizando a lista de discussão ksummit@lists.linux.dev, quais serão os + próximos passos. + +A Linux Foundation, conforme orientada pelo TAB, tomará as medidas necessárias +para apoiar e implementar este plano. From aa3bee451dc4217ed5391452dc524b27e813d97a Mon Sep 17 00:00:00 2001 From: Daniel Pereira Date: Mon, 23 Mar 2026 14:11:32 -0300 Subject: [PATCH 131/162] docs: pt_BR: Add translation for KVM x86 maintainer guide Translate the KVM x86 maintainer guidelines (maintainer-kvm-x86.rst) into Portuguese (pt_BR). This document covers the specific workflow, coding style, and testing requirements for the KVM x86 subsystem. Signed-off-by: Daniel Pereira Signed-off-by: Jonathan Corbet Message-ID: <20260323171133.88074-3-danielmaraboo@gmail.com> --- Documentation/translations/pt_BR/index.rst | 1 + .../pt_BR/process/maintainer-kvm-x86.rst | 435 ++++++++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst index efe6a4a3fef1..4a094d8b794f 100644 --- a/Documentation/translations/pt_BR/index.rst +++ b/Documentation/translations/pt_BR/index.rst @@ -74,3 +74,4 @@ kernel e sobre como ver seu trabalho integrado. Processo do subsistema de rede (netdev) Processo do subsistema SoC Conformidade de DTS para SoC + Processo do subsistema KVM x86 diff --git a/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst b/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst new file mode 100644 index 000000000000..6480ff08b9d8 --- /dev/null +++ b/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst @@ -0,0 +1,435 @@ +.. SPDX-License-Identifier: GPL-2.0 + +KVM x86 +======= + +Prefácio +-------- + +O KVM se esforça para ser uma comunidade acolhedora; as contribuições de +recém-chegados são valorizadas e incentivadas. Por favor, não se sinta +desanimado ou intimidado pela extensão deste documento e pelas muitas +regras/diretrizes que ele contém. Todo mundo comete erros e todo mundo já foi um +novato em algum momento. Desde que você faça um esforço honesto para seguir as +diretrizes do KVM x86, seja receptivo ao feedback e aprenda com os erros que +cometer, você será recebido de braços abertos, não com tochas e forquilhas. + +(TL;DR) +-------- +Testes são obrigatórios. Seja consistente com os estilos e padrões estabelecidos. + +Árvores +------- +O KVM x86 está atualmente em um período de transição: deixando de fazer parte da +árvore principal do KVM para se tornar "apenas mais uma arquitetura KVM". Como tal, +o KVM x86 está dividido entre a árvore principal do KVM, +``git.kernel.org/pub/scm/virt/kvm/kvm.git``, e uma árvore específica para KVM x86, +``github.com/kvm-x86/linux.git``. + +De modo geral, as correções (fixes) para o ciclo atual são aplicadas diretamente +na árvore principal do KVM, enquanto todo o desenvolvimento para o próximo ciclo +é roteado através da árvore do KVM x86. No caso improvável de uma correção para o +ciclo atual ser roteada através da árvore do KVM x86, ela será aplicada à branch +``fixes`` antes de seguir para a árvore principal do KVM. + +Note que espera-se que este período de transição dure bastante tempo, ou seja, +será o status quo em um futuro próximo. + +Branches +~~~~~~~~ +A árvore do KVM x86 é organizada em múltiplas branches de tópicos (topic +branches). O objetivo de usar branches de tópicos mais granulares é facilitar o +acompanhamento de uma área específica de desenvolvimento e limitar os danos +colaterais de erros humanos e/ou commits com bugs; por exemplo, descartar o +commit HEAD de uma branch de tópico não tem impacto nos hashes SHA1 de outros +commits em andamento, e a necessidade de rejeitar um pull request devido a bugs +atrasa apenas aquela branch de tópico específica. + +Todas as branches de tópicos, exceto a ``next`` e a ``fixes``, são incorporadas +na ``next`` via um "Cthulhu merge" conforme a necessidade, ou seja, sempre que +uma branch de tópico é atualizada. Como resultado, force pushes para a branch +``next`` são comuns. + +Ciclo de Vida +~~~~~~~~~~~~~ +As correções (fixes) destinadas ao lançamento atual, também conhecido como +mainline, são normalmente aplicadas diretamente na árvore principal do KVM, ou +seja, não passam pela árvore do KVM x86. + +As mudanças destinadas ao próximo lançamento são roteadas através da árvore do +KVM x86. Pull requests (do KVM x86 para o KVM principal) são enviados para cada +branch de tópico do KVM x86, normalmente na semana anterior à abertura da janela +de merge por Linus, por exemplo, na semana seguinte ao rc7 para lançamentos +"normais". Se tudo correr bem, as branches de tópicos são incorporadas ao pull +request principal do KVM enviado durante a janela de merge de Linus. + +A árvore do KVM x86 não possui sua própria janela de merge oficial, mas há um +"soft close" (fechamento flexível) por volta do rc5 para novos recursos, e um +"soft close" por volta do rc6 para correções (para o próximo lançamento; veja +acima para correções destinadas ao lançamento atual). + +Cronograma +---------- +As submissões são normalmente revisadas e aplicadas em ordem FIFO (primeiro a +entrar, primeiro a sair), com alguma margem de manobra para o tamanho de uma +série, patches que estão "cache hot", etc. Correções (fixes), especialmente para +o lançamento atual e/ou árvores estáveis (stable trees), têm prioridade na fila. +Patches que serão aceitos através de uma árvore não-KVM (mais frequentemente +através da árvore "tip") e/ou que possuam outros "acks"/revisões também ganham +certa prioridade. + +Note que a grande maioria das revisões é feita entre o rc1 e o rc6, +aproximadamente. O período entre o rc6 e o próximo rc1 é usado para colocar +outras tarefas em dia, ou seja, o "silêncio de rádio" durante este período não é +incomum. + +Pings para obter uma atualização de status são bem-vindos, mas tenha em mente o +tempo do ciclo de lançamento atual e tenha expectativas realistas. Se você está +dando um ping para aceitação — ou seja, não apenas para feedback ou uma +atualização — por favor, faça tudo o que puder, dentro do razoável, para garantir +que seus patches estejam prontos para o merge! Pings em séries que quebram o +build ou falham em testes resultam em mantenedores infelizes! + +Desenvolvimento +--------------- + +Árvore/Branch Base +~~~~~~~~~~~~~~~~~~ +Correções destinadas ao lançamento atual, também conhecido como mainline, devem +ser baseadas em ``git://git.kernel.org/pub/scm/virt/kvm/kvm.git master``. Note +que as correções não garantem inclusão automática no lançamento atual. Não +existe uma regra única, mas tipicamente apenas correções para bugs que sejam +urgentes, críticos e/ou que tenham sido introduzidos no lançamento atual devem +ser destinadas ao lançamento atual. + +Todo o restante deve ser baseado em ``kvm-x86/next``, ou seja, não há +necessidade de selecionar uma branch de tópico específica como base. Se houver +conflitos e/ou dependências entre as branches de tópicos, é trabalho do +mantenedor resolvê-los. + +A única exceção ao uso da ``kvm-x86/next`` como base é se um patch/série for uma +série multi-arquitetura (multi-arch), ou seja, possuir modificações não triviais +no código comum do KVM e/ou possuir mudanças mais do que superficiais no código +de outras arquiteturas. Patches/séries multi-arquitetura devem, em vez disso, +ser baseados em um ponto comum e estável no histórico do KVM, por exemplo, o +release candidate no qual a ``kvm-x86 next`` se baseia. Se você não tiver +certeza se um patch/série é verdadeiramente multi-arquitetura, erre pelo lado da +cautela e trate-o como tal, ou seja, use uma base comum. + +Estilo de Codificação +~~~~~~~~~~~~~~~~~~~~~ +Quando se trata de estilo, nomenclatura, padrões, etc., a consistência é a +prioridade número um no KVM x86. Se tudo mais falhar, siga o que já existe. + +Com algumas ressalvas listadas abaixo, siga o estilo de codificação preferido +dos mantenedores da árvore "tip" (:ref:`maintainer-tip-coding-style`), já que +patches/séries frequentemente tocam tanto arquivos do KVM quanto arquivos x86 +não-KVM, ou seja, atraem a atenção de mantenedores do KVM *e* da árvore "tip". + +O uso de "reverse fir tree" (árvore de abeto invertida), também conhecido como +"árvore de Natal invertida", para declarações de variáveis não é estritamente +obrigatório, embora ainda seja preferido. + +Exceto por alguns casos excepcionais, não use comentários kernel-doc para +funções. A grande maioria das funções "públicas" do KVM não são verdadeiramente +públicas, pois se destinam apenas ao consumo interno do KVM (há planos para +privatizar os headers e exports do KVM para reforçar isso). + +Comentários +~~~~~~~~~~~ +Escreva comentários usando o modo imperativo e evite pronomes. Use comentários +para fornecer uma visão geral de alto nível do código e/ou para explicar por +que o código faz o que faz. Não reitere o que o código faz literalmente; deixe +o código falar por si mesmo. Se o código em si for inescrutável, comentários +não ajudarão. + +Referências ao SDM e ao APM +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Grande parte da base de código do KVM está diretamente ligada ao comportamento +arquitetural definido no Manual de Desenvolvimento de Software (SDM) da Intel e +no Manual do Programador de Arquitetura (APM) da AMD. O uso de "Intel SDM" e +"AMD APM", ou até mesmo apenas "SDM" ou "APM", sem contexto adicional, é +perfeitamente aceitável. + +Não faça referência a seções, tabelas, figuras, etc., por número, especialmente +em comentários. Em vez disso, se necessário (veja abaixo), copie e cole o trecho +relevante e referencie seções/tabelas/figuras pelo nome. Os layouts do SDM e do +APM mudam constantemente e, portanto, os números/rótulos não são estáveis. + +De modo geral, não faça referência explícita nem copie e cole do SDM ou do APM +em comentários. Com poucas exceções, o KVM *deve* respeitar o comportamento +arquitetural; portanto, subentende-se que o comportamento do KVM está emulando o +comportamento do SDM e/ou do APM. Note que fazer referência ao SDM/APM em +changelogs para justificar a mudança e fornecer contexto é perfeitamente +aceitável e incentivado. + +Shortlog +~~~~~~~~ +O formato de prefixo preferencial é ``KVM: :``, onde ```` é um dos +seguintes:: + + - x86 + - x86/mmu + - x86/pmu + - x86/xen + - selftests + - SVM + - nSVM + - VMX + - nVMX + +**NÃO use x86/kvm!** ``x86/kvm`` é usado exclusivamente para mudanças no Linux +como convidado (guest) de um KVM, ou seja, para ``arch/x86/kernel/kvm.c``. Não +use nomes de arquivos ou caminhos completos de arquivos como prefixo do +assunto/shortlog. + +Note que estes não se alinham com as branches de tópicos (as branches de tópicos +se preocupam muito mais com conflitos de código). + +Todos os nomes são sensíveis a maiúsculas e minúsculas! ``KVM: x86:`` é bom, +``kvm: vmx:`` não é. + +Comece com letra maiúscula a primeira palavra da descrição condensada do patch, +mas omita a pontuação final. Ex.:: + + KVM: x86: Fix a null pointer dereference in function_xyz() + +e não:: + + kvm: x86: fix a null pointer dereference in function_xyz. + +Se um patch tocar em múltiplos tópicos, suba na árvore conceitual para encontrar +o primeiro pai comum (que geralmente é apenas ``x86``). Em caso de dúvida, +``git log caminho/do/arquivo`` deve fornecer uma dica razoável. + +Novos tópicos surgem ocasionalmente, mas, por favor, inicie uma discussão na +lista se desejar propor a introdução de um novo tópico; ou seja, não aja por +conta própria. + +Veja :ref:`the_canonical_patch_format` para mais informações, com uma ressalva: +não trate o limite de 70-75 caracteres como um limite absoluto e rígido. Em +vez disso, use 75 caracteres como um limite firme, mas não rígido, e use 80 +caracteres como um limite intransponível. Ou seja, permita que o shortlog +ultrapasse alguns caracteres do limite padrão se você tiver um bom motivo para +fazê-lo. + +Changelog +~~~~~~~~~ +O mais importante: escreva os changelogs usando o modo imperativo e evite o uso +de pronomes. + +Veja :ref:`describe_changes` para mais informações, com uma ressalva: comece com +uma breve descrição das mudanças reais e, em seguida, apresente o contexto e o +histórico. Note! Esta ordem entra em conflito direto com a abordagem preferida +da árvore "tip"! Por favor, siga o estilo preferido da árvore "tip" ao enviar +patches que visam primariamente o código de arch/x86 que _NÃO_ seja código KVM. + +Declarar o que um patch faz antes de mergulhar nos detalhes é preferido pelo KVM +x86 por vários motivos. Primeiro e mais importante, qual código está sendo +realmente alterado é, reconhecidamente, a informação mais importante e, +portanto, essa informação deve ser fácil de encontrar. Changelogs que escondem +"o que está mudando de fato" em uma única linha após 3 ou mais parágrafos de +histórico tornam muito difícil encontrar essa informação. + +Para uma revisão inicial, pode-se argumentar que "o que está quebrado" é mais +importante, mas para uma leitura rápida de logs e arqueologia do git, os +detalhes minuciosos importam cada vez menos. Por exemplo, ao fazer uma série de +"git blame", os detalhes de cada mudança ao longo do caminho são inúteis; os +detalhes só importam para o culpado. Fornecer "o que mudou" facilita determinar +rapidamente se um commit pode ou não ser de interesse. + +Outro benefício de declarar "o que está mudando" primeiro é que quase sempre é +possível declarar "o que está mudando" em uma única frase. Por outro lado, +exceto pelos bugs mais simples, todos exigem várias frases ou parágrafos para +descrever totalmente o problema. Se tanto "o que está mudando" quanto "qual é o +bug" forem super curtos, a ordem não importa. Mas se um for mais curto (quase +sempre o "o que está mudando"), então cobrir o mais curto primeiro é vantajoso +porque é menos inconveniente para leitores/revisores que têm uma preferência de +ordenação estrita. Ex: ter que pular uma frase para chegar ao contexto é menos +doloroso do que ter que pular três parágrafos para chegar ao "o que está +mudando". + +Correções (Fixes) +~~~~~~~~~~~~~~~~~ +Se uma mudança corrige um bug do KVM/kernel, adicione uma tag Fixes:, mesmo que +a mudança não precise ser portada (backported) para kernels estáveis, e mesmo +que a mudança corrija um bug em uma versão mais antiga. + +Por outro lado, se uma correção realmente precisar de backport, marque +explicitamente o patch com "Cc: stable@vger.kernel.org" (embora o e-mail em si +não precise enviar cópia para a lista stable); o KVM x86 opta por não realizar +o backport automático de tags Fixes: por padrão. Alguns patches selecionados +automaticamente são portados, mas exigem aprovação explícita do mantenedor +(pesquise por MANUALSEL). + +Referências a Funções +~~~~~~~~~~~~~~~~~~~~~ +Quando uma função for mencionada em um comentário, changelog ou shortlog (ou em +qualquer outro lugar, aliás), use o formato ``nome_da_funcao()``. Os parênteses +fornecem contexto e removem a ambiguidade da referência. + +Testes +------ +No mínimo, *todos* os patches de uma série devem compilar sem erros para +KVM_INTEL=m, KVM_AMD=m e KVM_WERROR=y. Compilar cada combinação possível de +Kconfigs não é viável, mas quanto mais, melhor. KVM_SMM, KVM_XEN, PROVE_LOCKING +e X86_64 são opções (knobs) particularmente interessantes para se testar. + +A execução de KVM selftests e KVM-unit-tests também é obrigatória (e, para +afirmar o óbvio, os testes precisam passar). A única exceção é para mudanças +que tenham probabilidade insignificante de afetar o comportamento em tempo de +execução, por exemplo, patches que apenas modificam comentários. Sempre que +possível e relevante, o teste tanto em Intel quanto em AMD é fortemente +preferido. A inicialização de uma VM real é incentivada, mas não obrigatória. + +Para mudanças que tocam o código de shadow paging do KVM, executar com o TDP +(EPT/NPT) desabilitado é obrigatório. Para mudanças que afetam o código comum da +MMU do KVM, a execução com o TDP desabilitado é fortemente incentivada. Para +todas as outras mudanças, se o código sendo modificado depender de e/ou +interagir com um parâmetro de módulo (module param), o teste com as +configurações relevantes é obrigatório. + +Note que o KVM selftests e o KVM-unit-tests possuem falhas conhecidas. Se você +suspeitar que uma falha não se deve às suas alterações, verifique se a *exata +mesma* falha ocorre com e sem as suas mudanças. + +Mudanças que tocam a documentação em reStructuredText, ou seja, arquivos .rst, +devem compilar o htmldocs de forma limpa, ou seja, sem novos avisos (warnings) +ou erros. + +Se você não puder testar totalmente uma mudança, por exemplo, devido à falta de +hardware, declare claramente qual nível de teste você foi capaz de realizar, +por exemplo, na cover letter (carta de apresentação). + +Novos Recursos +~~~~~~~~~~~~~~ +Com uma exceção, novos recursos *devem* vir acompanhados de cobertura de testes. +Testes específicos do KVM não são estritamente obrigatórios, por exemplo, se a +cobertura for fornecida ao executar uma VM convidada (guest) suficientemente +habilitada, ou ao executar um selftest de kernel relacionado em uma VM, mas +testes dedicados do KVM são preferidos em todos os casos. Casos de teste +negativos, em particular, são obrigatórios para a habilitação de novos recursos +de hardware, já que fluxos de erro e exceção raramente são exercitados +simplesmente ao executar uma VM. + +A única exceção a esta regra é se o KVM estiver simplesmente anunciando suporte +para um recurso via KVM_GET_SUPPORTED_CPUID, ou seja, para instruções/recursos +que o KVM não pode impedir um convidado de usar e para os quais não há uma +habilitação real. + +Note que "novos recursos" não significa apenas "novos recursos de hardware"! +Novos recursos que não podem ser bem validados usando os KVM selftests e/ou +KVM-unit-tests existentes devem vir acompanhados de testes. + +Enviar o desenvolvimento de novos recursos sem testes para obter feedback +antecipado é mais do que bem-vindo, mas tais submissões devem ser marcadas como +RFC, e a carta de apresentação (cover letter) deve declarar claramente que tipo +de feedback é solicitado/esperado. Não abuse do processo de RFC; as RFCs +normalmente não receberão uma revisão profunda. + +Correções de Bugs +~~~~~~~~~~~~~~~~~ +Exceto por bugs "óbvios" encontrados por inspeção, as correções devem vir +acompanhadas de um reprodutor (reproducer) para o bug que está sendo corrigido. +Em muitos casos, o reprodutor é implícito, por exemplo, para erros de build e +falhas de teste, mas ainda assim deve estar claro para os leitores o que está +quebrado e como verificar a correção. Alguma margem de manobra é dada para +bugs encontrados através de cargas de trabalho ou testes não públicos, mas a +disponibilização de testes de regressão para tais bugs é fortemente preferida. + +Em geral, testes de regressão são preferidos para qualquer bug que não seja +trivial de ser atingido. Por exemplo, mesmo que o bug tenha sido originalmente +encontrado por um fuzzer como o syzkaller, um teste de regressão direcionado +pode ser justificável se o bug exigir que se atinja uma condição de corrida do +tipo "uma em um milhão". + +Note que os bugs do KVM raramente são urgentes *e* não triviais de reproduzir. +Pergunte a si mesmo se um bug é realmente o fim do mundo antes de enviar uma +correção sem um reprodutor. + +Postagem +-------- + +Links +~~~~~ +Não faça referência explícita a relatórios de bugs, versões anteriores de um +patch/série, etc., através de cabeçalhos ``In-Reply-To:``. O uso de +``In-Reply-To:`` torna-se uma bagunça infernal para grandes séries e/ou quando +o número de versões aumenta, e o ``In-Reply-To:`` é inútil para qualquer +pessoa que não tenha a mensagem original, por exemplo, se alguém não estava +em cópia (Cc) no relatório do bug ou se a lista de destinatários mudar entre +as versões. + +Para vincular a um relatório de bug, versão anterior ou qualquer coisa de +interesse, use links do lore. Para referenciar versão(ões) anterior(es), de modo +geral, não inclua um Link: no changelog, pois não há necessidade de registrar o +histórico no git; ou seja, coloque o link na carta de apresentação (cover +letter) ou na seção que o git ignora. Forneça um Link: formal para relatórios +de bugs e/ou discussões que levaram ao patch. O contexto de por que uma mudança +foi feita é altamente valioso para futuros leitores. + +Base do Git (Git Base) +~~~~~~~~~~~~~~~~~~~~~~ +Se você estiver usando o git versão 2.9.0 ou posterior (Googlers, isso inclui +todos vocês!), use ``git format-patch`` com a flag ``--base`` para incluir +automaticamente as informações da árvore base nos patches gerados. + +Note que ``--base=auto`` funciona conforme o esperado se, e somente se, o +upstream de uma branch estiver definido para a branch de tópico base; por +exemplo, ele fará a coisa errada se o seu upstream estiver definido para o seu +repositório pessoal para fins de backup. Uma solução "auto" alternativa é +derivar os nomes das suas branches de desenvolvimento com base no seu tópico +KVM x86 e alimentar isso no ``--base``. Por exemplo, +``x86/pmu/minha_branch`` e, em seguida, escrever um pequeno wrapper para +extrair ``pmu`` do nome da branch atual para resultar em ``--base=x/pmu``, onde +``x`` é o nome que seu repositório usa para rastrear o remoto do KVM x86. + +Postagem Conjunta de Testes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +KVM selftests que estão associados a mudanças no KVM, por exemplo, testes de +regressão para correções de bugs, devem ser postados junto com as mudanças do +KVM como uma única série. As regras padrão do kernel para bissecção (bisection) +se aplicam, ou seja, mudanças no KVM que resultem em falhas de teste devem ser +ordenadas após as atualizações dos selftests e, vice-versa, novos testes que +falhem devido a bugs do KVM devem ser ordenados após as correções do KVM. + +KVM-unit-tests devem *sempre* ser postados separadamente. Ferramentas, como o +b4 am, não sabem que o KVM-unit-tests é um repositório separado e ficam +confusas quando os patches de uma série se aplicam a árvores diferentes. Para +vincular os patches do KVM-unit-tests aos patches do KVM, poste primeiro as +mudanças do KVM e, em seguida, forneça um link do lore para o patch/série do +KVM no(s) patch(es) do KVM-unit-tests. + +Notificações +------------ +Quando um patch/série é oficialmente aceito, um e-mail de notificação será +enviado em resposta à postagem original (carta de apresentação para séries de +múltiplos patches). A notificação incluirá a árvore e a branch de tópico, +juntamente com os SHA1s dos commits dos patches aplicados. + +Se um subconjunto de patches for aplicado, isso será claramente declarado na +notificação. A menos que seja dito o contrário, subentende-se que quaisquer +patches na série que não foram aceitos precisam de mais trabalho e devem ser +enviados em uma nova versão. + +Se, por algum motivo, um patch for descartado após ter sido oficialmente +aceito, uma resposta será enviada ao e-mail de notificação explicando o porquê +do descarte, bem como os próximos passos. + +Estabilidade de SHA1 +~~~~~~~~~~~~~~~~~~~~ +Os SHA1s não têm garantia de serem 100% estáveis até que cheguem na árvore do +Linus! Um SHA1 é *geralmente* estável uma vez que a notificação tenha sido +enviada, mas imprevistos acontecem. Na maioria dos casos, uma atualização no +e-mail de notificação será fornecida se o SHA1 de um patch aplicado mudar. No +entanto, em alguns cenários, por exemplo, se todas as branches do KVM x86 +precisarem de rebase, as notificações individuais não serão enviadas. + +Vulnerabilidades +---------------- +Bugs que podem ser explorados pelo convidado (guest) para atacar o hospedeiro +(host) (kernel ou espaço do usuário), ou que podem ser explorados por uma VM +aninhada (nested) contra o *seu* próprio hospedeiro (L2 atacando L1), são de +interesse particular para o KVM. Por favor, siga o protocolo em +:ref:`securitybugs` se você suspeitar que um bug possa levar a um escape, +vazamento de dados, etc. From 0a4f3ef9880e505d41817419b0255d6552776143 Mon Sep 17 00:00:00 2001 From: Akiyoshi Kurita Date: Mon, 9 Mar 2026 19:50:15 +0900 Subject: [PATCH 132/162] docs: ja_JP: process: translate second half of 'Describe your changes' Translate the remaining part of the "Describe your changes" section in Documentation/translations/ja_JP/process/submitting-patches.rst. Follow review comments on wording and line wrapping, and cover guidance on self-contained patch descriptions, imperative mood, commit references, and Link:/Closes:/Fixes: tags. Signed-off-by: Akiyoshi Kurita Acked-by: Akira Yokosawa Signed-off-by: Jonathan Corbet Message-ID: <20260309105015.309116-1-weibu@redadmin.org> --- .../ja_JP/process/submitting-patches.rst | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/Documentation/translations/ja_JP/process/submitting-patches.rst b/Documentation/translations/ja_JP/process/submitting-patches.rst index b89e63a1f65c..3bb2383871e1 100644 --- a/Documentation/translations/ja_JP/process/submitting-patches.rst +++ b/Documentation/translations/ja_JP/process/submitting-patches.rst @@ -96,3 +96,87 @@ Linux の多くの環境は、上流から特定のパッチだけを取り込 .. TODO: Convert to file-local cross-reference when the destination is translated. + +パッチまたはパッチシリーズを投稿/再投稿する際は、その完全な +説明と、それを正当化する理由を含めてください。単に、これが +パッチ(シリーズ)のバージョン N であるとだけ書かないでください。 +サブシステムメンテナが以前のパッチ版や参照先 URL をさかのぼって +パッチ説明を探し、それをパッチに補うことを期待してはいけません。 +つまり、パッチ(シリーズ)とその説明は、それだけで完結しているべき +です。これはメンテナとレビューアの双方に有益です。レビューアの +中には、以前のパッチ版を受け取っていない人もいるでしょう。 + +変更内容は命令形で記述してください。たとえば、 +「make xyzzy do frotz」とし、 +「[This patch] makes xyzzy do frotz」や +「[I] changed xyzzy to do frotz」 +のようには書かないでください。あたかもコードベースに対して、 +その振る舞いを変えるよう命令しているかのように書いてください。 + +特定のコミットに言及したい場合は、コミットの SHA-1 ID だけを +書かないでください。レビューアがそれが何についてのものかを +把握しやすくなるよう、コミットの 1 行要約も含めてください。例:: + + Commit e21d2170f36602ae2708 ("video: remove unnecessary + platform_set_drvdata()") removed the unnecessary + platform_set_drvdata(), but left the variable "dev" unused, + delete it. + +また、SHA-1 ID は少なくとも先頭 12 文字を使うようにしてください。 +カーネルのリポジトリには非常に多くのオブジェクトがあるため、 +それより短い ID では衝突が現実に起こり得ます。いま 6 文字の ID に +衝突がなくても、5 年後もそうだとは限らないことに注意してください。 + +変更に関連する議論や、その背景情報が Web 上で参照できる場合は、 +それを指す ``Link:`` タグを追加してください。パッチが過去の +メーリングリストでの議論や、Web に記録された何かの結果であるなら、 +それを示してください。 + +メーリングリストのアーカイブへリンクする場合は、できれば +lore.kernel.org のメッセージアーカイブサービスを使ってください。 +リンク URL を作るには、そのメッセージの ``Message-ID`` ヘッダの内容 +から、前後の山括弧を取り除いたものを使います。例:: + + Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI + +実際にリンクが機能し、該当するメッセージを指していることを +確認してください。ただし、外部リソースを見なくても説明が理解できる +ようにするよう努めてください。 + +メーリングリストのアーカイブやバグへの URL を示すだけでなく、 +投稿されたパッチに至った議論の要点も要約してください。 + +パッチがバグを修正するものであれば、メーリングリストのアーカイブや +公開バグトラッカー上の報告を指す URL を付けて、``Closes:`` タグを +使ってください。例:: + + Closes: https://example.com/issues/1234 + +このようなタグ付きのコミットが適用されたとき、自動的に issue を +閉じられるバグトラッカーもあります。メーリングリストを監視している +ボットの中には、そのようなタグを追跡して一定の動作を行うものも +あります。非公開のバグトラッカーや無効な URL は禁止です。 + +パッチが特定のコミットに含まれるバグを修正するものであれば、 +たとえば ``git bisect`` で問題を見つけた場合には、SHA-1 ID の +先頭少なくとも 12 文字と 1 行要約を含めて、``Fixes:`` タグを +使ってください。タグを複数行に分割してはいけません。タグは +解析スクリプトを単純にするため、「75 桁で折り返す」規則の +例外です。 + +例:: + + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") + +上の形式を ``git log`` や ``git show`` で出力しやすくするために、 +次の ``git config`` 設定を使えます:: + + [core] + abbrev = 12 + [pretty] + fixes = Fixes: %h ("%s") + +呼び出し例:: + + $ git log -1 --pretty=fixes 54a4f0239f2e + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") From 8545d9bc4bd0801e0bdfbfdfdc2532ff31236ddf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 27 Mar 2026 11:41:57 -0400 Subject: [PATCH 133/162] scripts/checkpatch: add Assisted-by: tag validation The coding-assistants.rst documentation defines the Assisted-by: tag format for AI-assisted contributions as: Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] This format does not use an email address, so checkpatch currently reports a false positive about an invalid email when encountering this tag. Add Assisted-by: to the recognized signature tags and standard signature list. When an Assisted-by: tag is found, validate it instead of checking for an email address. Examples of passing tags: - Claude:claude-3-opus coccinelle sparse - FOO:BAR.baz - Copilot Github:claude-3-opus - GitHub Copilot:Claude Opus 4.6 - My Cool Agent:v1.2.3 coccinelle sparse Examples of tags triggering the new warning: - Claude coccinelle sparse - JustAName - :missing-agent Cc: Jani Nikula Assisted-by: Claude:claude-opus-4.6 Co-developed-by: Alex Hung Signed-off-by: Alex Hung Signed-off-by: Harry Wentland Cc: stable@vger.kernel.org Signed-off-by: Jonathan Corbet Message-ID: <20260327154157.162962-1-harry.wentland@amd.com> --- scripts/checkpatch.pl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e56374662ff7..b8d961d77ff4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -641,6 +641,7 @@ our $signature_tags = qr{(?xi: Reviewed-by:| Reported-by:| Suggested-by:| + Assisted-by:| To:| Cc: )}; @@ -737,7 +738,7 @@ sub find_standard_signature { my ($sign_off) = @_; my @standard_signature_tags = ( 'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:', - 'Reviewed-by:', 'Reported-by:', 'Suggested-by:' + 'Reviewed-by:', 'Reported-by:', 'Suggested-by:', 'Assisted-by:' ); foreach my $signature (@standard_signature_tags) { return $signature if (get_edit_distance($sign_off, $signature) <= 2); @@ -3105,6 +3106,15 @@ sub process { } } +# Assisted-by: uses format AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] instead of email + if ($sign_off =~ /^assisted-by:$/i) { + if ($email !~ /^[^:]+:\S+(\s+\S+)*$/) { + WARN("BAD_ASSISTED_BY", + "Assisted-by: should use format: 'Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]'\n" . $herecurr); + } + next; + } + my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); if ($suggested_email eq "") { From d642acfd597e3ec37138f9a8f5a634845e3612fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Mar 2026 06:57:48 +0100 Subject: [PATCH 134/162] doc tools: better handle KBUILD_VERBOSE As reported by Jacob, there are troubles when KBUILD_VERBOSE is set at the environment. Fix it on both kernel-doc and sphinx-build-wrapper. Reported-by: Jacob Keller Closes: https://lore.kernel.org/linux-doc/9367d899-53af-4d9c-9320-22fc4dbadca5@intel.com/ Signed-off-by: Mauro Carvalho Chehab Tested-by: Jacob Keller Signed-off-by: Jonathan Corbet Message-ID: <7a99788db75630fb14828d612c0fd77c45ec1891.1774591065.git.mchehab+huawei@kernel.org> --- tools/docs/sphinx-build-wrapper | 7 ++++++- tools/lib/python/kdoc/kdoc_files.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/docs/sphinx-build-wrapper b/tools/docs/sphinx-build-wrapper index 2c63d28f639d..1bb962202784 100755 --- a/tools/docs/sphinx-build-wrapper +++ b/tools/docs/sphinx-build-wrapper @@ -238,7 +238,12 @@ class SphinxBuilder: self.latexopts = os.environ.get("LATEXOPTS", "") if not verbose: - verbose = bool(os.environ.get("KBUILD_VERBOSE", "") != "") + try: + verbose = bool(int(os.environ.get("KBUILD_VERBOSE", 0))) + except ValueError: + # Handles an eventual case where verbosity is not a number + # like KBUILD_VERBOSE="" + verbose = False if verbose is not None: self.verbose = verbose diff --git a/tools/lib/python/kdoc/kdoc_files.py b/tools/lib/python/kdoc/kdoc_files.py index 2428cfc4e843..ed82b6e6ab25 100644 --- a/tools/lib/python/kdoc/kdoc_files.py +++ b/tools/lib/python/kdoc/kdoc_files.py @@ -238,7 +238,12 @@ class KernelFiles(): """ if not verbose: - verbose = bool(os.environ.get("KBUILD_VERBOSE", 0)) + try: + verbose = bool(int(os.environ.get("KBUILD_VERBOSE", 0))) + except ValueError: + # Handles an eventual case where verbosity is not a number + # like KBUILD_VERBOSE="" + verbose = False if out_style is None: out_style = OutputFormat() From 7f7f468548cee80d221cbc77e639fe99e113ff99 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 26 Mar 2026 16:32:24 -0700 Subject: [PATCH 135/162] Documentation: Provide hints on how to debug Python GDB scripts By default GDB does not print a full stack of its integrated Python interpreter, thus making the debugging of GDB scripts more painful than it has to be. Suggested-by: Radu Rendec Signed-off-by: Florian Fainelli Reviewed-by: Radu Rendec Signed-off-by: Jonathan Corbet Message-ID: <20260326233226.2248817-1-florian.fainelli@broadcom.com> --- Documentation/process/debugging/gdb-kernel-debugging.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/process/debugging/gdb-kernel-debugging.rst b/Documentation/process/debugging/gdb-kernel-debugging.rst index 9475c759c722..53e225760a4d 100644 --- a/Documentation/process/debugging/gdb-kernel-debugging.rst +++ b/Documentation/process/debugging/gdb-kernel-debugging.rst @@ -173,3 +173,12 @@ this is just a snapshot of the initial version:: Detailed help can be obtained via "help " for commands and "help function " for convenience functions. + +Debugging GDB scripts +--------------------- + +GDB does not enable a full Python backtrace which can make debugging GDB +scripts more difficult than necessary. The following will allow for printing a +full backtrace of the python environment:: + + (gdb) set python print-stack full From 06dbdc5da152e30fbd09b37afdca2fdec9da2165 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 30 Mar 2026 10:29:54 -0600 Subject: [PATCH 136/162] Revert "scripts: ver_linux: expand and fix list" This reverts commit 98e7b5752898f74788098bef51f53205e365ab9d. I had not intended to apply this version of this patch; take it out and we'll try again later. Signed-off-by: Jonathan Corbet --- scripts/ver_linux | 50 +++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/scripts/ver_linux b/scripts/ver_linux index 458c30a44f8d..d6f2362d3792 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -7,7 +7,7 @@ BEGIN { usage = "If some fields are empty or look unusual you may have an old version.\n" - usage = usage "Compare to the current minimal requirements in Documentation/process/changes.rst\n" + usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" print usage system("uname -a") @@ -18,22 +18,22 @@ BEGIN { libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$" printversion("GNU C", version("gcc -dumpversion")) - printversion("GNU make", version("make --version")) - printversion("binutils", version("ld -v")) - printversion("util-linux", version("mount --version")) + printversion("GNU Make", version("make --version")) + printversion("Binutils", version("ld -v")) + printversion("Util-linux", version("mount --version")) printversion("Mount", version("mount --version")) printversion("Module-init-tools", version("depmod -V")) - printversion("e2fsprogs", version("e2fsck -V")) - printversion("jfsutils", version("fsck.jfs -V")) - printversion("xfsprogs", version("xfs_db -V")) - printversion("pcmciautils", version("pccardctl -V")) + printversion("E2fsprogs", version("tune2fs")) + printversion("Jfsutils", version("fsck.jfs -V")) + printversion("Xfsprogs", version("xfs_db -V")) + printversion("Pcmciautils", version("pccardctl -V")) printversion("Pcmcia-cs", version("cardmgr -V")) - printversion("quota-tools", version("quota -V")) + printversion("Quota-tools", version("quota -V")) printversion("PPP", version("pppd --version")) printversion("Isdn4k-utils", version("isdnctrl")) - printversion("nfs-utils", version("showmount --version")) - printversion("bison", version("bison --version")) - printversion("flex", version("flex --version")) + printversion("Nfs-utils", version("showmount --version")) + printversion("Bison", version("bison --version")) + printversion("Flex", version("flex --version")) while ("ldconfig -p 2>/dev/null" | getline > 0) if ($NF ~ libc || $NF ~ libcpp) @@ -41,35 +41,13 @@ BEGIN { printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver) printversion("Dynamic linker (ldd)", version("ldd --version")) - printversion("procps", version("ps --version")) + printversion("Procps", version("ps --version")) printversion("Net-tools", version("ifconfig --version")) printversion("Kbd", version("loadkeys -V")) printversion("Console-tools", version("loadkeys -V")) printversion("Sh-utils", version("expr --v")) - printversion("udev", version("udevadm --version")) + printversion("Udev", version("udevadm --version")) printversion("Wireless-tools", version("iwconfig --version")) - printversion("bash", version("bash --version")) - printversion("bc", version("bc --version")) - printversion("bindgen", version("bindgen --version")) - printversion("btrfs-progs", version("btrfs --version")) - printversion("Clang", version("clang --version")) - printversion("gdb", version("gdb -version")) - printversion("GNU awk", version("gawk --version")) - printversion("GNU tar", version("tar --version")) - printversion("GRUB", version("grub-install --version")) - printversion("GRUB2", version("grub2-install --version")) - printversion("gtags", version("gtags --version")) - printversion("iptables", version("iptables -V")) - printversion("kmod", version("kmod -V")) - printversion("mcelog", version("mcelog --version")) - printversion("mkimage", version("mkimage --version")) - printversion("openssl", version("openssl version")) - printversion("pahole", version("pahole --version")) - printversion("Python", version("python3 -V")) - printversion("Rust", version("rustc --version")) - printversion("Sphinx", version("sphinx-build --version")) - printversion("squashfs-tools", version("mksquashfs -version")) - while ("sort /proc/modules" | getline > 0) { mods = mods sep $1 From d8a224f519c6e7079ca3471e32c1e55fde7a2fdd Mon Sep 17 00:00:00 2001 From: Manuel Ebner Date: Wed, 25 Mar 2026 20:46:17 +0100 Subject: [PATCH 137/162] docs: changes/ver_linux: fix entries and add several tools Some of the entries in both Documentation/process/changes.rst and script/ver_linux were obsolete; update them to reflect the current way of getting version information. Many were missing altogether; add the relevant information for: bash, bc, bindgen, btrfs-progs, Clang, gdb, GNU awk, GNU tar, GRUB, GRUB2, gtags, iptables, kmod, mcelog, mkimage, openssl, pahole, Python, Rust, Sphinx, squashfs-tools Signed-off-by: Manuel Ebner [jc: rewrote changelog] Signed-off-by: Jonathan Corbet Message-ID: <20260325194616.78093-2-manuelebner@mailbox.org> --- Documentation/process/changes.rst | 14 +++++---- scripts/ver_linux | 49 ++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index f9f6f5c47882..bfad07ad0176 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -19,12 +19,13 @@ Current Minimal Requirements Upgrade to at **least** these software revisions before thinking you've encountered a bug! If you're unsure what version you're currently -running, the suggested command should tell you. +running, the suggested command should tell you. For a list of the programs +on your system including their version execute ./scripts/ver_linux Again, keep in mind that this list assumes you are already functionally running a Linux kernel. Also, not all tools are necessary on all systems; obviously, if you don't have any PC Card hardware, for example, -you probably needn't concern yourself with pcmciautils. +you probably do not need to concern yourself with pcmciautils. ====================== =============== ======================================== Program Minimal version Command to check the version @@ -40,7 +41,7 @@ flex 2.5.35 flex --version bison 2.0 bison --version pahole 1.22 pahole --version util-linux 2.10o mount --version -kmod 13 depmod -V +kmod 13 kmod -V e2fsprogs 1.41.4 e2fsck -V jfsutils 1.1.3 fsck.jfs -V xfsprogs 2.6.0 xfs_db -V @@ -51,8 +52,8 @@ quota-tools 3.09 quota -V PPP 2.4.0 pppd --version nfs-utils 1.0.5 showmount --version procps 3.2.0 ps --version -udev 081 udevd --version -grub 0.93 grub --version || grub-install --version +udev 081 udevadm --version +GRUB 0.93 grub --version || grub-install --version mcelog 0.6 mcelog --version iptables 1.4.2 iptables -V openssl & libcrypto 1.0.0 openssl version @@ -62,7 +63,8 @@ GNU tar 1.28 tar --version gtags (optional) 6.6.5 gtags --version mkimage (optional) 2017.01 mkimage --version Python 3.9.x python3 --version -GNU AWK (optional) 5.1.0 gawk --version +GNU awk (optional) 5.1.0 gawk --version +gdb 7.2 gdb --version ====================== =============== ======================================== .. [#f1] Sphinx is needed only to build the Kernel documentation diff --git a/scripts/ver_linux b/scripts/ver_linux index d6f2362d3792..fab0c68a6c52 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -7,7 +7,7 @@ BEGIN { usage = "If some fields are empty or look unusual you may have an old version.\n" - usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" + usage = usage "Compare to the current minimal requirements in Documentation/process/changes.rst\n" print usage system("uname -a") @@ -18,22 +18,22 @@ BEGIN { libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$" printversion("GNU C", version("gcc -dumpversion")) - printversion("GNU Make", version("make --version")) - printversion("Binutils", version("ld -v")) - printversion("Util-linux", version("mount --version")) + printversion("GNU make", version("make --version")) + printversion("binutils", version("ld -v")) + printversion("util-linux", version("mount --version")) printversion("Mount", version("mount --version")) printversion("Module-init-tools", version("depmod -V")) - printversion("E2fsprogs", version("tune2fs")) - printversion("Jfsutils", version("fsck.jfs -V")) - printversion("Xfsprogs", version("xfs_db -V")) - printversion("Pcmciautils", version("pccardctl -V")) + printversion("e2fsprogs", version("e2fsck -V")) + printversion("jfsutils", version("fsck.jfs -V")) + printversion("xfsprogs", version("xfs_db -V")) + printversion("pcmciautils", version("pccardctl -V")) printversion("Pcmcia-cs", version("cardmgr -V")) - printversion("Quota-tools", version("quota -V")) + printversion("quota-tools", version("quota -V")) printversion("PPP", version("pppd --version")) printversion("Isdn4k-utils", version("isdnctrl")) - printversion("Nfs-utils", version("showmount --version")) - printversion("Bison", version("bison --version")) - printversion("Flex", version("flex --version")) + printversion("nfs-utils", version("showmount --version")) + printversion("bison", version("bison --version")) + printversion("flex", version("flex --version")) while ("ldconfig -p 2>/dev/null" | getline > 0) if ($NF ~ libc || $NF ~ libcpp) @@ -41,13 +41,34 @@ BEGIN { printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver) printversion("Dynamic linker (ldd)", version("ldd --version")) - printversion("Procps", version("ps --version")) + printversion("procps", version("ps --version")) printversion("Net-tools", version("ifconfig --version")) printversion("Kbd", version("loadkeys -V")) printversion("Console-tools", version("loadkeys -V")) printversion("Sh-utils", version("expr --v")) - printversion("Udev", version("udevadm --version")) + printversion("udev", version("udevadm --version")) printversion("Wireless-tools", version("iwconfig --version")) + printversion("bash", version("bash --version")) + printversion("bc", version("bc --version")) + printversion("bindgen", version("bindgen --version")) + printversion("btrfs-progs", version("btrfs --version")) + printversion("Clang", version("clang --version")) + printversion("gdb", version("gdb -version")) + printversion("GNU awk", version("gawk --version")) + printversion("GNU tar", version("tar --version")) + printversion("GRUB", version("grub-install --version")) + printversion("GRUB2", version("grub2-install --version")) + printversion("gtags", version("gtags --version")) + printversion("iptables", version("iptables -V")) + printversion("kmod", version("kmod -V")) + printversion("mcelog", version("mcelog --version")) + printversion("mkimage", version("mkimage --version")) + printversion("openssl", version("openssl version")) + printversion("pahole", version("pahole --version")) + printversion("Python", version("python3 -V")) + printversion("Rust", version("rustc --version")) + printversion("Sphinx", version("sphinx-build --version")) + printversion("squashfs-tools", version("mksquashfs -version")) while ("sort /proc/modules" | getline > 0) { mods = mods sep $1 From ece7e57afd51e0b807bef5a43e2d0b1cd6e9c86f Mon Sep 17 00:00:00 2001 From: Manuel Ebner Date: Wed, 25 Mar 2026 20:48:12 +0100 Subject: [PATCH 138/162] docs: changes.rst and ver_linux: sort the lists Sort the lists of tools in both scripts/ver_linux and Documentation/process/changes.rst into alphabetical order, facilitating comparison between the two. Signed-off-by: Manuel Ebner [jc: rewrote changelog] Signed-off-by: Jonathan Corbet Message-ID: <20260325194811.78509-2-manuelebner@mailbox.org> --- Documentation/process/changes.rst | 64 ++++++++++++++-------------- scripts/ver_linux | 70 +++++++++++++++---------------- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index bfad07ad0176..adbd52869458 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -30,41 +30,41 @@ you probably do not need to concern yourself with pcmciautils. ====================== =============== ======================================== Program Minimal version Command to check the version ====================== =============== ======================================== -GNU C 8.1 gcc --version -Clang/LLVM (optional) 15.0.0 clang --version -Rust (optional) 1.78.0 rustc --version -bindgen (optional) 0.65.1 bindgen --version -GNU make 4.0 make --version bash 4.2 bash --version -binutils 2.30 ld -v -flex 2.5.35 flex --version -bison 2.0 bison --version -pahole 1.22 pahole --version -util-linux 2.10o mount --version -kmod 13 kmod -V -e2fsprogs 1.41.4 e2fsck -V -jfsutils 1.1.3 fsck.jfs -V -xfsprogs 2.6.0 xfs_db -V -squashfs-tools 4.0 mksquashfs -version -btrfs-progs 0.18 btrfs --version -pcmciautils 004 pccardctl -V -quota-tools 3.09 quota -V -PPP 2.4.0 pppd --version -nfs-utils 1.0.5 showmount --version -procps 3.2.0 ps --version -udev 081 udevadm --version -GRUB 0.93 grub --version || grub-install --version -mcelog 0.6 mcelog --version -iptables 1.4.2 iptables -V -openssl & libcrypto 1.0.0 openssl version bc 1.06.95 bc --version -Sphinx\ [#f1]_ 3.4.3 sphinx-build --version -GNU tar 1.28 tar --version -gtags (optional) 6.6.5 gtags --version -mkimage (optional) 2017.01 mkimage --version -Python 3.9.x python3 --version -GNU awk (optional) 5.1.0 gawk --version +bindgen (optional) 0.65.1 bindgen --version +binutils 2.30 ld -v +bison 2.0 bison --version +btrfs-progs 0.18 btrfs --version +Clang/LLVM (optional) 15.0.0 clang --version +e2fsprogs 1.41.4 e2fsck -V +flex 2.5.35 flex --version gdb 7.2 gdb --version +GNU awk (optional) 5.1.0 gawk --version +GNU C 8.1 gcc --version +GNU make 4.0 make --version +GNU tar 1.28 tar --version +GRUB 0.93 grub --version || grub-install --version +gtags (optional) 6.6.5 gtags --version +iptables 1.4.2 iptables -V +jfsutils 1.1.3 fsck.jfs -V +kmod 13 kmod -V +mcelog 0.6 mcelog --version +mkimage (optional) 2017.01 mkimage --version +nfs-utils 1.0.5 showmount --version +openssl & libcrypto 1.0.0 openssl version +pahole 1.22 pahole --version +pcmciautils 004 pccardctl -V +PPP 2.4.0 pppd --version +procps 3.2.0 ps --version +Python 3.9.x python3 --version +quota-tools 3.09 quota -V +Rust (optional) 1.78.0 rustc --version +Sphinx\ [#f1]_ 3.4.3 sphinx-build --version +squashfs-tools 4.0 mksquashfs -version +udev 081 udevadm --version +util-linux 2.10o mount --version +xfsprogs 2.6.0 xfs_db -V ====================== =============== ======================================== .. [#f1] Sphinx is needed only to build the Kernel documentation diff --git a/scripts/ver_linux b/scripts/ver_linux index fab0c68a6c52..00bdaf30d590 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -17,58 +17,58 @@ BEGIN { libc = "libc[.]so[.][0-9]+$" libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$" + printversion("bash", version("bash --version")) + printversion("bc", version("bc --version")) + printversion("bindgen", version("bindgen --version")) + printversion("binutils", version("ld -v")) + printversion("bison", version("bison --version")) + printversion("btrfs-progs", version("btrfs --version")) + printversion("Clang", version("clang --version")) + printversion("Console-tools", version("loadkeys -V")) + printversion("Dynamic linker (ldd)", version("ldd --version")) + printversion("e2fsprogs", version("e2fsck -V")) + printversion("flex", version("flex --version")) + printversion("gdb", version("gdb -version")) + printversion("GNU awk", version("gawk --version")) printversion("GNU C", version("gcc -dumpversion")) printversion("GNU make", version("make --version")) - printversion("binutils", version("ld -v")) - printversion("util-linux", version("mount --version")) - printversion("Mount", version("mount --version")) - printversion("Module-init-tools", version("depmod -V")) - printversion("e2fsprogs", version("e2fsck -V")) - printversion("jfsutils", version("fsck.jfs -V")) - printversion("xfsprogs", version("xfs_db -V")) - printversion("pcmciautils", version("pccardctl -V")) - printversion("Pcmcia-cs", version("cardmgr -V")) - printversion("quota-tools", version("quota -V")) - printversion("PPP", version("pppd --version")) + printversion("GNU tar", version("tar --version")) + printversion("GRUB2", version("grub2-install --version")) + printversion("GRUB", version("grub-install --version")) + printversion("gtags", version("gtags --version")) + printversion("iptables", version("iptables -V")) printversion("Isdn4k-utils", version("isdnctrl")) - printversion("nfs-utils", version("showmount --version")) - printversion("bison", version("bison --version")) - printversion("flex", version("flex --version")) + printversion("jfsutils", version("fsck.jfs -V")) + printversion("Kbd", version("loadkeys -V")) + printversion("kmod", version("kmod -V")) while ("ldconfig -p 2>/dev/null" | getline > 0) if ($NF ~ libc || $NF ~ libcpp) if (!seen[ver = version("readlink " $NF)]++) printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver) - printversion("Dynamic linker (ldd)", version("ldd --version")) - printversion("procps", version("ps --version")) - printversion("Net-tools", version("ifconfig --version")) - printversion("Kbd", version("loadkeys -V")) - printversion("Console-tools", version("loadkeys -V")) - printversion("Sh-utils", version("expr --v")) - printversion("udev", version("udevadm --version")) - printversion("Wireless-tools", version("iwconfig --version")) - printversion("bash", version("bash --version")) - printversion("bc", version("bc --version")) - printversion("bindgen", version("bindgen --version")) - printversion("btrfs-progs", version("btrfs --version")) - printversion("Clang", version("clang --version")) - printversion("gdb", version("gdb -version")) - printversion("GNU awk", version("gawk --version")) - printversion("GNU tar", version("tar --version")) - printversion("GRUB", version("grub-install --version")) - printversion("GRUB2", version("grub2-install --version")) - printversion("gtags", version("gtags --version")) - printversion("iptables", version("iptables -V")) - printversion("kmod", version("kmod -V")) printversion("mcelog", version("mcelog --version")) printversion("mkimage", version("mkimage --version")) + printversion("Module-init-tools", version("depmod -V")) + printversion("Mount", version("mount --version")) + printversion("Net-tools", version("ifconfig --version")) + printversion("nfs-utils", version("showmount --version")) printversion("openssl", version("openssl version")) printversion("pahole", version("pahole --version")) + printversion("Pcmcia-cs", version("cardmgr -V")) + printversion("pcmciautils", version("pccardctl -V")) + printversion("PPP", version("pppd --version")) + printversion("procps", version("ps --version")) printversion("Python", version("python3 -V")) + printversion("quota-tools", version("quota -V")) printversion("Rust", version("rustc --version")) + printversion("Sh-utils", version("expr --v")) printversion("Sphinx", version("sphinx-build --version")) printversion("squashfs-tools", version("mksquashfs -version")) + printversion("udev", version("udevadm --version")) + printversion("util-linux", version("mount --version")) + printversion("Wireless-tools", version("iwconfig --version")) + printversion("xfsprogs", version("xfs_db -V")) while ("sort /proc/modules" | getline > 0) { mods = mods sep $1 From 07f6cb18c5dd627023e0810cfd51203392f55990 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2026 20:09:42 +0100 Subject: [PATCH 139/162] tools: unittest_helper: add a quiet mode On quiet mode, only report errors. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <27556792ff70e6267ecd19c258149d380db8d423.1774551940.git.mchehab+huawei@kernel.org> --- tools/lib/python/unittest_helper.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/lib/python/unittest_helper.py b/tools/lib/python/unittest_helper.py index 55d444cd73d4..f3cba5120401 100755 --- a/tools/lib/python/unittest_helper.py +++ b/tools/lib/python/unittest_helper.py @@ -141,7 +141,7 @@ class Summary(unittest.TestResult): super().addSkip(test, reason) self._record_test(test, f"SKIP ({reason})") - def printResults(self): + def printResults(self, verbose): """ Print results using colors if tty. """ @@ -174,10 +174,15 @@ class Summary(unittest.TestResult): # Print results for module_name, classes in self.test_results.items(): - print(f"{module_name}:") + if verbose: + print(f"{module_name}:") for class_name, tests in classes.items(): - print(f" {class_name}:") + if verbose: + print(f" {class_name}:") for test_name, status in tests: + if not verbose and status in [ "OK", "EXPECTED_FAIL" ]: + continue + # Get base status without reason for SKIP if status.startswith("SKIP"): status_code = status.split()[0] @@ -187,7 +192,8 @@ class Summary(unittest.TestResult): print( f" {test_name + ':':<{max_length}}{color}{status}{COLORS['reset']}" ) - print() + if verbose: + print() # Print summary print(f"\nRan {self.testsRun} tests", end="") @@ -230,6 +236,7 @@ class TestUnits: """Returns a parser for command line arguments.""" parser = argparse.ArgumentParser(description="Test runner with regex filtering") parser.add_argument("-v", "--verbose", action="count", default=1) + parser.add_argument("-q", "--quiet", action="store_true") parser.add_argument("-f", "--failfast", action="store_true") parser.add_argument("-k", "--keyword", help="Regex pattern to filter test methods") @@ -279,7 +286,10 @@ class TestUnits: if not caller_file and not suite: raise TypeError("Either caller_file or suite is needed at TestUnits") - verbose = args.verbose + if args.quiet: + verbose = 0 + else: + verbose = args.verbose if not env: env = os.environ.copy() @@ -334,7 +344,7 @@ class TestUnits: failfast=args.failfast) result = runner.run(suite) if resultclass: - result.printResults() + result.printResults(verbose) sys.exit(not result.wasSuccessful()) From 210a923aab5b81b6930715c4e845d58d406b154d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2026 20:09:43 +0100 Subject: [PATCH 140/162] docs: kdoc_diff: add a helper tool to help checking kdoc regressions Checking for regressions at kernel-doc can be hard. Add a helper tool to make such task easier. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Message-ID: <24b3116a78348b13a74d1ff5e141160ef9705dd3.1774551940.git.mchehab+huawei@kernel.org> --- tools/docs/kdoc_diff | 508 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100755 tools/docs/kdoc_diff diff --git a/tools/docs/kdoc_diff b/tools/docs/kdoc_diff new file mode 100755 index 000000000000..1aa16bdccaa3 --- /dev/null +++ b/tools/docs/kdoc_diff @@ -0,0 +1,508 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2026: Mauro Carvalho Chehab . +# +# pylint: disable=R0903,R0912,R0913,R0914,R0915,R0917 + +""" +docdiff - Check differences between kernel‑doc output between two different +commits. + +Examples +-------- + +Compare the kernel‑doc output between the last two 5.15 releases:: + + $ kdoc_diff v6.18..v6.19 + +Both outputs are cached + +Force a complete documentation scan and clean any previous cache from +6.19 to the current HEAD:: + + $ kdoc_diff 6.19.. --full --clean + +Check differences only on a single driver since origin/main:: + + $ kdoc_diff origin/main drivers/media + +Generate an YAML file and use it to check for regressions:: + + $ kdoc_diff HEAD~ drivers/media --regression + + +""" + +import os +import sys +import argparse +import subprocess +import shutil +import re +import signal + +from glob import iglob + + +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) +WORK_DIR = os.path.abspath(os.path.join(SRC_DIR, "../..")) + +KDOC_BINARY = os.path.join(SRC_DIR, "kernel-doc") +KDOC_PARSER_TEST = os.path.join(WORK_DIR, "tools/unittests/test_kdoc_parser.py") + +CACHE_DIR = ".doc_diff_cache" +YAML_NAME = "out.yaml" + +DIR_NAME = { + "full": os.path.join(CACHE_DIR, "full"), + "partial": os.path.join(CACHE_DIR, "partial"), + "no-cache": os.path.join(CACHE_DIR, "no_cache"), + "tmp": os.path.join(CACHE_DIR, "__tmp__"), +} + +class GitHelper: + """Handles all Git operations""" + + def __init__(self, work_dir=None): + self.work_dir = work_dir + + def is_inside_repository(self): + """Check if we're inside a Git repository""" + try: + output = subprocess.check_output(["git", "rev-parse", + "--is-inside-work-tree"], + cwd=self.work_dir, + stderr=subprocess.STDOUT, + universal_newlines=True) + + return output.strip() == "true" + except subprocess.CalledProcessError: + return False + + def is_valid_commit(self, commit_hash): + """ + Validate that a ref (branch, tag, commit hash, etc.) can be + resolved to a commit. + """ + try: + subprocess.check_output(["git", "rev-parse", commit_hash], + cwd=self.work_dir, + stderr=subprocess.STDOUT) + return True + except subprocess.CalledProcessError: + return False + + def get_short_hash(self, commit_hash): + """Get short commit hash""" + try: + return subprocess.check_output(["git", "rev-parse", "--short", + commit_hash], + cwd=self.work_dir, + stderr=subprocess.STDOUT, + universal_newlines=True).strip() + except subprocess.CalledProcessError: + return "" + + def has_uncommitted_changes(self): + """Check for uncommitted changes""" + try: + subprocess.check_output(["git", "diff-index", + "--quiet", "HEAD", "--"], + cwd=self.work_dir, + stderr=subprocess.STDOUT) + return False + except subprocess.CalledProcessError: + return True + + def get_current_branch(self): + """Get current branch name""" + return subprocess.check_output(["git", "branch", "--show-current"], + cwd=self.work_dir, + universal_newlines=True).strip() + + def checkout_commit(self, commit_hash, quiet=True): + """Checkout a commit safely""" + args = ["git", "checkout", "-f"] + if quiet: + args.append("-q") + args.append(commit_hash) + try: + subprocess.check_output(args, cwd=self.work_dir, + stderr=subprocess.STDOUT) + + # Double-check if branch actually switched + branch = self.get_short_hash("HEAD") + if commit_hash != branch: + raise RuntimeError(f"Branch changed to '{branch}' instead of '{commit_hash}'") + + return True + except subprocess.CalledProcessError as e: + print(f"ERROR: Failed to checkout {commit_hash}: {e}", + file=sys.stderr) + return False + + +class CacheManager: + """Manages persistent cache directories""" + + def __init__(self, work_dir): + self.work_dir = work_dir + + def initialize(self): + """Create cache directories if they don't exist""" + for dir_path in DIR_NAME.values(): + abs_path = os.path.join(self.work_dir, dir_path) + if not os.path.exists(abs_path): + os.makedirs(abs_path, exist_ok=True, mode=0o755) + + def get_commit_cache(self, commit_hash, path): + """Generate cache path for a commit""" + hash_short = GitHelper(self.work_dir).get_short_hash(commit_hash) + if not hash_short: + hash_short = commit_hash + + return os.path.join(path, hash_short) + +class KernelDocRunner: + """Runs kernel-doc documentation generator""" + + def __init__(self, work_dir, kdoc_binary): + self.work_dir = work_dir + self.kdoc_binary = kdoc_binary + self.kdoc_files = None + + def find_kdoc_references(self): + """Find all files marked with kernel-doc:: directives""" + if self.kdoc_files: + print("Using cached Kdoc refs") + return self.kdoc_files + + print("Finding kernel-doc entries in Documentation...") + + files = os.path.join(self.work_dir, 'Documentation/**/*.rst') + pattern = re.compile(r"^\.\.\s+kernel-doc::\s*(\S+)") + kdoc_files = set() + + for file_path in iglob(files, recursive=True): + try: + with open(file_path, 'r', encoding='utf-8') as fp: + for line in fp: + match = pattern.match(line.strip()) + if match: + kdoc_files.add(match.group(1)) + + except OSError: + continue + + self.kdoc_files = list(kdoc_files) + + return self.kdoc_files + + def gen_yaml(self, yaml_file, kdoc_files): + """Runs kernel-doc to generate a yaml file with man and rst.""" + cmd = [self.kdoc_binary, "--man", "--rst", "--yaml", yaml_file] + cmd += kdoc_files + + print(f"YAML regression test file will be stored at: {yaml_file}") + + try: + subprocess.check_call(cmd, cwd=self.work_dir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError: + return False + + return True + + def run_unittest(self, yaml_file): + """Run unit tests with the generated yaml file""" + cmd = [KDOC_PARSER_TEST, "-q", "--yaml", yaml_file] + result = subprocess.run(cmd, cwd=self.work_dir) + + if result.returncode: + print("To check for problems, try to run it again with -v\n") + print("Use -k to filter results\n\n\t$", end="") + print(" ".join(cmd) + "\n") + + return True + + def normal_run(self, tmp_dir, output_dir, kdoc_files): + """Generate man, rst and errors, storing them at tmp_dir.""" + os.makedirs(tmp_dir, exist_ok=True) + + try: + with open(os.path.join(tmp_dir, "man.log"), "w", encoding="utf-8") as out: + subprocess.check_call([self.kdoc_binary, "--man"] + kdoc_files, + cwd=self.work_dir, + stdout=out, stderr=subprocess.DEVNULL) + + with open(os.path.join(tmp_dir, "rst.log"), "w", encoding="utf-8") as out: + with open(os.path.join(tmp_dir, "err.log"), "w", encoding="utf-8") as err: + subprocess.check_call([self.kdoc_binary, "--rst"] + kdoc_files, + cwd=self.work_dir, + stdout=out, stderr=err) + except subprocess.CalledProcessError: + return False + + if output_dir: + os.replace(tmp_dir, output_dir) + + return True + + def run(self, commit_hash, tmp_dir, output_dir, kdoc_files, is_regression, + is_end): + """Run kernel-doc on its several ways""" + if not kdoc_files: + raise RuntimeError("No kernel-doc references found") + + git_helper = GitHelper(self.work_dir) + if not git_helper.checkout_commit(commit_hash, quiet=True): + raise RuntimeError(f"ERROR: can't checkout commit {commit_hash}") + + print(f"Processing {commit_hash}...") + + if not is_regression: + return self.normal_run(tmp_dir, output_dir, kdoc_files) + + yaml_file = os.path.join(tmp_dir, YAML_NAME) + + if not is_end: + return self.gen_yaml(yaml_file, kdoc_files) + + return self.run_unittest(yaml_file) + +class DiffManager: + """Compare documentation output directories with an external diff.""" + def __init__(self, diff_tool="diff", diff_args=None): + self.diff_tool = diff_tool + # default: unified, no context, ignore whitespace changes + self.diff_args = diff_args or ["-u0", "-w"] + + def diff_directories(self, dir1, dir2): + """Compare two directories using an external diff.""" + print(f"\nDiffing {dir1} and {dir2}:") + + dir1_files = set() + dir2_files = set() + has_diff = False + + for root, _, files in os.walk(dir1): + for file in files: + dir1_files.add(os.path.relpath(os.path.join(root, file), dir1)) + for root, _, files in os.walk(dir2): + for file in files: + dir2_files.add(os.path.relpath(os.path.join(root, file), dir2)) + + common_files = sorted(dir1_files & dir2_files) + for file in common_files: + f1 = os.path.join(dir1, file) + f2 = os.path.join(dir2, file) + + cmd = [self.diff_tool] + self.diff_args + [f1, f2] + try: + result = subprocess.run( + cmd, capture_output=True, text=True, check=False + ) + if result.stdout: + has_diff = True + print(f"\n{file}") + print(result.stdout, end="") + except FileNotFoundError: + print(f"ERROR: {self.diff_tool} not found") + sys.exit(1) + + # Show files that exist only in one directory + only_in_dir1 = dir1_files - dir2_files + only_in_dir2 = dir2_files - dir1_files + if only_in_dir1 or only_in_dir2: + has_diff = True + print("\nDifferential files:") + for f in sorted(only_in_dir1): + print(f" - {f} (only in {dir1})") + for f in sorted(only_in_dir2): + print(f" + {f} (only in {dir2})") + + if not has_diff: + print("\nNo differences between those two commits") + + +class SignalHandler(): + """Signal handler class.""" + + def restore(self, force_exit=False): + """Restore original HEAD state.""" + if self.restored: + return + + print(f"Restoring original branch: {self.original_head}") + try: + subprocess.check_call( + ["git", "checkout", "-f", self.original_head], + cwd=self.git_helper.work_dir, + stderr=subprocess.STDOUT, + ) + except subprocess.CalledProcessError as e: + print(f"Failed to restore: {e}", file=sys.stderr) + + for sig, handler in self.old_handler.items(): + signal.signal(sig, handler) + + self.restored = True + + if force_exit: + sys.exit(1) + + def signal_handler(self, sig, _): + """Handle interrupt signals.""" + print(f"\nSignal {sig} received. Restoring original state...") + + self.restore(force_exit=True) + + def __enter__(self): + """Allow using it via with command.""" + for sig in [signal.SIGINT, signal.SIGTERM]: + self.old_handler[sig] = signal.getsignal(sig) + signal.signal(sig, self.signal_handler) + + return self + + def __exit__(self, *args): + """Restore signals at the end of with block.""" + self.restore() + + def __init__(self, git_helper, original_head): + self.git_helper = git_helper + self.original_head = original_head + self.old_handler = {} + self.restored = False + +def parse_commit_range(value): + """Handle a commit range.""" + if ".." not in value: + begin = value + end = "HEAD" + else: + begin, _, end = value.partition("..") + if not end: + end = "HEAD" + + if not begin: + raise argparse.ArgumentTypeError("Need a commit begginning") + + + print(f"Range: {begin} to {end}") + + return begin, end + + +def main(): + """Main code""" + parser = argparse.ArgumentParser(description="Compare kernel documentation between commits") + parser.add_argument("commits", type=parse_commit_range, + help="commit range like old..new") + parser.add_argument("files", nargs="*", + help="files to process – if supplied the --full flag is ignored") + + parser.add_argument("--full", "-f", action="store_true", + help="Force a full scan of Documentation/*") + + parser.add_argument("--regression", "-r", action="store_true", + help="Use YAML format to check for regressions") + + parser.add_argument("--work-dir", "-w", default=WORK_DIR, + help="work dir (default: %(default)s)") + + parser.add_argument("--clean", "-c", action="store_true", + help="Clean caches") + + args = parser.parse_args() + + if args.files and args.full: + raise argparse.ArgumentError(args.full, + "cannot combine '--full' with an explicit file list") + + work_dir = os.path.abspath(args.work_dir) + + # Initialize cache + cache = CacheManager(work_dir) + cache.initialize() + + # Validate git repository + git_helper = GitHelper(work_dir) + if not git_helper.is_inside_repository(): + raise RuntimeError("Must run inside Git repository") + + old_commit, new_commit = args.commits + + old_commit = git_helper.get_short_hash(old_commit) + new_commit = git_helper.get_short_hash(new_commit) + + # Validate commits + for commit in [old_commit, new_commit]: + if not git_helper.is_valid_commit(commit): + raise RuntimeError(f"Commit '{commit}' does not exist") + + # Check for uncommitted changes + if git_helper.has_uncommitted_changes(): + raise RuntimeError("Uncommitted changes present. Commit or stash first.") + + runner = KernelDocRunner(git_helper.work_dir, KDOC_BINARY) + + # Get files to be parsed + cache_msg = " (results will be cached)" + if args.full: + kdoc_files = ["."] + diff_type = "full" + print(f"Parsing all files at {work_dir}") + if not args.files: + diff_type = "partial" + kdoc_files = runner.find_kdoc_references() + print(f"Parsing files with kernel-doc markups at {work_dir}/Documentation") + else: + diff_type = "no-cache" + cache_msg = "" + kdoc_files = args.files + + tmp_dir = DIR_NAME["tmp"] + out_path = DIR_NAME[diff_type] + + if not args.regression: + print(f"Output will be stored at: {out_path}{cache_msg}") + + # Just in case - should never happen in practice + if not kdoc_files: + raise argparse.ArgumentError(args.files, + "No kernel-doc references found") + + original_head = git_helper.get_current_branch() + + old_cache = cache.get_commit_cache(old_commit, out_path) + new_cache = cache.get_commit_cache(new_commit, out_path) + + with SignalHandler(git_helper, original_head): + if args.clean or diff_type == "no-cache": + for cache_dir in [old_cache, new_cache]: + if cache_dir and os.path.exists(cache_dir): + shutil.rmtree(cache_dir) + + if args.regression or not os.path.exists(old_cache): + old_success = runner.run(old_commit, tmp_dir, old_cache, kdoc_files, + args.regression, False) + else: + old_success = True + + if args.regression or not os.path.exists(new_cache): + new_success = runner.run(new_commit, tmp_dir, new_cache, kdoc_files, + args.regression, True) + else: + new_success = True + + if not (old_success and new_success): + raise RuntimeError("Failed to generate documentation") + + if not args.regression: + diff_manager = DiffManager() + diff_manager.diff_directories(old_cache, new_cache) + +if __name__ == "__main__": + main() From 999084ee0b111aaeb3e0b37b25d180c53ff6b702 Mon Sep 17 00:00:00 2001 From: Akira Yokosawa Date: Thu, 26 Mar 2026 20:46:37 +0900 Subject: [PATCH 141/162] docs/ja_JP: submitting-patches: Amend "Describe your changes" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make the translation of "Describe your changes" (into "変更内容を記述する") easier to follow, do some rewording and rephrasing, as well as fixing a couple of mistranslations. Signed-off-by: Akira Yokosawa Signed-off-by: Jonathan Corbet Message-ID: <20260326114637.144601-1-akiyks@gmail.com> --- .../ja_JP/process/submitting-patches.rst | 107 +++++++++--------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/Documentation/translations/ja_JP/process/submitting-patches.rst b/Documentation/translations/ja_JP/process/submitting-patches.rst index 3bb2383871e1..9d63220abd15 100644 --- a/Documentation/translations/ja_JP/process/submitting-patches.rst +++ b/Documentation/translations/ja_JP/process/submitting-patches.rst @@ -55,67 +55,66 @@ Documentation/process/maintainer-handbooks.rst. 変更内容を記述する ------------------ -問題を記述してください。あなたのパッチが 1 行のバグ修正であっても、 +まず問題点を記べてください。あなたのパッチが 1 行のバグ修正であっても、 5000 行の新機能であっても、それを行う動機となった根本的な問題が -必ずあるはずです。修正すべき価値のある問題が存在し、レビューアが -最初の段落以降を読む意味があることを納得させてください。 +必ずあるはずです。レビューアが、修正すべき問題がたしかに存在し、冒頭の +段落の続きを読むべきだと納得できるように書いてください。 -ユーザーから見える影響を記述してください。クラッシュやロックアップは +次にユーザーから見える影響を記述してください。クラッシュやロックアップは 分かりやすいですが、すべてのバグがそこまで露骨とは限りません。 たとえコードレビュー中に見つかった問題であっても、ユーザーに どのような影響があり得るかを記述してください。 Linux の多くの環境は、上流から特定のパッチだけを取り込む二次的な 安定版ツリーや、ベンダー/製品固有のツリーのカーネルで動いています。 -したがって、変更を下流へ適切に流す助けになる情報(発生条件、dmesg +したがって、変更を適切に下流へ流す助けになる情報(発生条件、dmesg の抜粋、クラッシュ内容、性能劣化、レイテンシのスパイク、 ロックアップ等)があれば記載してください。 -最適化とトレードオフを定量的に示してください。パフォーマンス、 +次に最適化とトレードオフを定量的に示してください。パフォーマンス、 メモリ消費量、スタックフットプリント、バイナリサイズの改善を主張する 場合は、それを裏付ける数値を記載してください。 -また、目に見えないコストについても記述してください。最適化は通常 -無料ではなく、CPU・メモリ・可読性の間でのトレードオフになります。 -ヒューリスティクスの場合は、異なるワークロード間でのトレードオフに +また、目に見えないコストについても記述してください。多くの場合、 +最適化は CPU・メモリ・可読性の間でのトレードオフとなります。 +ヒューリスティクスの場合は、異なるワークロード間でのトレードオフと なります。レビューアがコストとメリットを比較検討できるよう、 -最適化によって予想されるデメリットも記述してください。 +最適化に伴って想定されるデメリットも記述してください。 -問題を明確にできたら、実際にどのような対策を講じているかを技術的に -詳しく記述してください。レビューアがコードが意図したとおりに動作して -いるかを確認できるよう、変更内容を平易な言葉で書き下すことが重要です。 +問題点の明確化が済んだら、実際にどのような対策を講じているかを技術的に +詳しく説明してください。コードが意図したとおりに動作していることを +レビューアが確認できるよう、変更内容を平易な言葉で書き下すことが重要です。 -パッチ説明を Linux のソースコード管理システム ``git`` の -「コミットログ」としてそのまま取り込める形で書けば、メンテナは -助かります。詳細は原文の該当節を参照してください。 +パッチの説明が Linux のソースコード管理システム ``git`` の「コミットログ」 +としてそのまま取り込める形で書かれていれば、メンテナは助かります。 +詳細は原文の該当節 ("The canonical patch format") を参照してください。 .. TODO: Convert to file-local cross-reference when the destination is translated. 1 つのパッチでは 1 つの問題だけを解決してください。記述が長くなり -始めたら、パッチを分割すべきサインです。詳細は原文の該当節を参照 -してください。 +始めたら、それはパッチを分割すべきサインです。 +詳細は原文の該当節 ("Separate your changes") を参照してください。 .. TODO: Convert to file-local cross-reference when the destination is translated. パッチまたはパッチシリーズを投稿/再投稿する際は、その完全な -説明と、それを正当化する理由を含めてください。単に、これが -パッチ(シリーズ)のバージョン N であるとだけ書かないでください。 -サブシステムメンテナが以前のパッチ版や参照先 URL をさかのぼって -パッチ説明を探し、それをパッチに補うことを期待してはいけません。 +説明と、それを正当化する理由を含めてください。単に「これはパッチ +(シリーズ)のバージョン N です」とだけ書くのは避けてください。 +サブシステムメンテナが以前のパッチバージョンや参照先 URL をさかのぼって +パッチ記述を探し、それをパッチに補うことを期待してはいけません。 つまり、パッチ(シリーズ)とその説明は、それだけで完結しているべき です。これはメンテナとレビューアの双方に有益です。レビューアの -中には、以前のパッチ版を受け取っていない人もいるでしょう。 +中には、以前のパッチバージョンを受け取っていない人もいるでしょう。 -変更内容は命令形で記述してください。たとえば、 -「make xyzzy do frotz」とし、 -「[This patch] makes xyzzy do frotz」や -「[I] changed xyzzy to do frotz」 -のようには書かないでください。あたかもコードベースに対して、 -その振る舞いを変えるよう命令しているかのように書いてください。 +変更内容は、あたかもコードベースに対してその振る舞いを変えるように +命令するかの如く、(訳補: 英語の)命令形で記述してください。たとえば、 +"[This patch] makes xyzzy do frotz" や +"[I] changed xyzzy to do frotz" のような言い回しを避け、 +"make xyzzy do frotz" のように書いてください。 -特定のコミットに言及したい場合は、コミットの SHA-1 ID だけを -書かないでください。レビューアがそれが何についてのものかを -把握しやすくなるよう、コミットの 1 行要約も含めてください。例:: +特定のコミットに言及したい場合に、コミットの SHA-1 ID だけを +書くのは避けてください。レビューアがそれが何についてのものかを +把握しやすいよう、コミットの 1 行要約も含めてください。例:: Commit e21d2170f36602ae2708 ("video: remove unnecessary platform_set_drvdata()") removed the unnecessary @@ -123,28 +122,29 @@ Linux の多くの環境は、上流から特定のパッチだけを取り込 delete it. また、SHA-1 ID は少なくとも先頭 12 文字を使うようにしてください。 -カーネルのリポジトリには非常に多くのオブジェクトがあるため、 -それより短い ID では衝突が現実に起こり得ます。いま 6 文字の ID に -衝突がなくても、5 年後もそうだとは限らないことに注意してください。 +カーネルのリポジトリには\ **非常に多くの**\ オブジェクトがあるため、 +それより短い ID では衝突が現実問題となります。6 文字の ID が今現在 +衝突しないからといって、5 年後もそうであるとは限らないことを念頭に +置いてください。 変更に関連する議論や、その背景情報が Web 上で参照できる場合は、 -それを指す ``Link:`` タグを追加してください。パッチが過去の -メーリングリストでの議論や、Web に記録された何かの結果であるなら、 +それを指す 'Link:' タグを追加してください。過去のメーリングリスト +での議論や、Web に記録された何かに由来するパッチならば、 それを示してください。 -メーリングリストのアーカイブへリンクする場合は、できれば -lore.kernel.org のメッセージアーカイブサービスを使ってください。 -リンク URL を作るには、そのメッセージの ``Message-ID`` ヘッダの内容 -から、前後の山括弧を取り除いたものを使います。例:: +メーリングリストのアーカイブへリンクする場合は、できれば lore.kernel.org +のメッセージアーカイブサービスを使ってください。リンク URL を作るには、 +そのメッセージの ``Message-ID`` ヘッダの内容から、前後の山括弧を取り除いた +ものを使います。例:: Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI 実際にリンクが機能し、該当するメッセージを指していることを -確認してください。ただし、外部リソースを見なくても説明が理解できる -ようにするよう努めてください。 +確認してください。 +ただし、外部リソースを見なくても説明が理解できるようにするよう努めてください。 メーリングリストのアーカイブやバグへの URL を示すだけでなく、 -投稿されたパッチに至った議論の要点も要約してください。 +投稿されたパッチに至った議論のポイントも要約してください。 パッチがバグを修正するものであれば、メーリングリストのアーカイブや 公開バグトラッカー上の報告を指す URL を付けて、``Closes:`` タグを @@ -153,23 +153,22 @@ lore.kernel.org のメッセージアーカイブサービスを使ってくだ Closes: https://example.com/issues/1234 このようなタグ付きのコミットが適用されたとき、自動的に issue を -閉じられるバグトラッカーもあります。メーリングリストを監視している +閉じるバグトラッカーもあります。メーリングリストを監視している ボットの中には、そのようなタグを追跡して一定の動作を行うものも -あります。非公開のバグトラッカーや無効な URL は禁止です。 +あります。ただし、非公開バグトラッカーの(訳補: 部外者が)閲覧できない +URL は禁止です。 -パッチが特定のコミットに含まれるバグを修正するものであれば、 -たとえば ``git bisect`` で問題を見つけた場合には、SHA-1 ID の -先頭少なくとも 12 文字と 1 行要約を含めて、``Fixes:`` タグを +パッチが特定のコミットに含まれるバグを修正するもの、たとえば +``git bisect`` で問題を見つけたものの場合には、SHA-1 ID の +先頭少なくとも 12 文字と 1 行要約を含めて 'Fixes:' タグを 使ってください。タグを複数行に分割してはいけません。タグは 解析スクリプトを単純にするため、「75 桁で折り返す」規則の -例外です。 - -例:: +例外です。例:: Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") -上の形式を ``git log`` や ``git show`` で出力しやすくするために、 -次の ``git config`` 設定を使えます:: +``git log`` や ``git show`` の出力を上の形式で整形させるには、 +次の ``git config`` 設定が使えます:: [core] abbrev = 12 From 4663a5a2a3483b5f6b049cf7e9705773ab35e6c7 Mon Sep 17 00:00:00 2001 From: "Zenghui Yu (Huawei)" Date: Wed, 11 Mar 2026 15:09:40 +0800 Subject: [PATCH 142/162] docs: proc: remove description of prof_cpu_mask Commit 2e5449f4f21a ("profiling: Remove create_prof_cpu_mask().") said that no one would create /proc/irq/prof_cpu_mask since commit 1f44a225777e ("s390: convert interrupt handling to use generic hardirq", 2013). Remove the outdated description. While at it, fix another minor typo (s/DMS/DMA/). Signed-off-by: Zenghui Yu (Huawei) Signed-off-by: Jonathan Corbet Message-ID: <20260311070940.94838-1-zenghui.yu@linux.dev> --- Documentation/filesystems/proc.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index e2d22a424dcd..873761087f8d 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -743,7 +743,7 @@ files are there, and which are missing. in the kernel image cpuinfo Info about the CPU devices Available devices (block and character) - dma Used DMS channels + dma Used DMA channels filesystems Supported filesystems driver Various drivers grouped here, currently rtc (2.4) execdomains Execdomains, related to security (2.4) @@ -877,14 +877,13 @@ i386 and x86_64 platforms support the new IRQ vector displays. Of some interest is the introduction of the /proc/irq directory to 2.4. It could be used to set IRQ to CPU affinity. This means that you can "hook" an IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the -irq subdir is one subdir for each IRQ, and two files; default_smp_affinity and -prof_cpu_mask. +irq subdir is one subdir for each IRQ, and default_smp_affinity. For example:: > ls /proc/irq/ - 0 10 12 14 16 18 2 4 6 8 prof_cpu_mask - 1 11 13 15 17 19 3 5 7 9 default_smp_affinity + 0 10 12 14 16 18 2 4 6 8 default_smp_affinity + 1 11 13 15 17 19 3 5 7 9 > ls /proc/irq/0/ smp_affinity @@ -915,9 +914,6 @@ The node file on an SMP system shows the node to which the device using the IRQ reports itself as being attached. This hardware locality information does not include information about any possible driver locality preference. -prof_cpu_mask specifies which CPUs are to be profiled by the system wide -profiler. Default value is ffffffff (all CPUs if there are only 32 of them). - The way IRQs are routed is handled by the IO-APIC, and it's Round Robin between all the CPUs which are allowed to handle it. As usual the kernel has more info than you and does a better job than you, so the defaults are the From 83725f1d980b92789f99db0ea756979017c37ac3 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 31 Mar 2026 08:31:58 -0600 Subject: [PATCH 143/162] Revert "scripts/checkpatch: add Assisted-by: tag validation" This reverts commit 8545d9bc4bd0801e0bdfbfdfdc2532ff31236ddf. Unbeknownst to me, and unremarked upon by the checkpatch maintainer, this same problem was also solved in the mm tree. Fixing it once is enough, so this one comes out. Signed-off-by: Jonathan Corbet --- scripts/checkpatch.pl | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b8d961d77ff4..e56374662ff7 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -641,7 +641,6 @@ our $signature_tags = qr{(?xi: Reviewed-by:| Reported-by:| Suggested-by:| - Assisted-by:| To:| Cc: )}; @@ -738,7 +737,7 @@ sub find_standard_signature { my ($sign_off) = @_; my @standard_signature_tags = ( 'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:', - 'Reviewed-by:', 'Reported-by:', 'Suggested-by:', 'Assisted-by:' + 'Reviewed-by:', 'Reported-by:', 'Suggested-by:' ); foreach my $signature (@standard_signature_tags) { return $signature if (get_edit_distance($sign_off, $signature) <= 2); @@ -3106,15 +3105,6 @@ sub process { } } -# Assisted-by: uses format AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] instead of email - if ($sign_off =~ /^assisted-by:$/i) { - if ($email !~ /^[^:]+:\S+(\s+\S+)*$/) { - WARN("BAD_ASSISTED_BY", - "Assisted-by: should use format: 'Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]'\n" . $herecurr); - } - next; - } - my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); if ($suggested_email eq "") { From 6252e5c1c20e381adadfc91fa8af691017a268f1 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 30 Mar 2026 16:25:11 -0600 Subject: [PATCH 144/162] docs: add an Assisted-by mention to submitting-patches.rst We now require disclosure of the use of coding assistants, but our core submitting-patches document does not mention that. Add a brief mention with a pointer to Documentation/process/coding-assistants.rst Signed-off-by: Jonathan Corbet Message-ID: <877bqtlzug.fsf@trenco.lwn.net> --- Documentation/process/submitting-patches.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index c88e75bf0534..d7290e208e72 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -634,6 +634,16 @@ bugzilla.kernel.org is a public place in this sense, but email addresses used there are private; so do not expose them in tags, unless the person used them in earlier contributions. +Using Assisted-by: +------------------ + +If you used any sort of advanced coding tool in the creation of your patch, +you need to acknowledge that use by adding an Assisted-by tag. Failure to +do so may impede the acceptance of your work. Please see +Documentation/process/coding-assistants.rst for details regarding the +acknowledgment of coding assistants. + + .. _the_canonical_patch_format: The canonical patch format From ba0e9fdab3f8cbd1e70ecd288f3255b8b57c932a Mon Sep 17 00:00:00 2001 From: Gleb Golovko Date: Wed, 8 Apr 2026 00:28:18 +0300 Subject: [PATCH 145/162] docs: fix typo in zoran driver documentation Replace "an a few" with "and a few" in Documentation/driver-api/media/drivers/zoran.rst. Signed-off-by: Gleb Golovko Signed-off-by: Jonathan Corbet Message-ID: <20260407212818.925-1-gaben123001@gmail.com> --- Documentation/driver-api/media/drivers/zoran.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/media/drivers/zoran.rst b/Documentation/driver-api/media/drivers/zoran.rst index 3e05b7f0442a..2538473c3233 100644 --- a/Documentation/driver-api/media/drivers/zoran.rst +++ b/Documentation/driver-api/media/drivers/zoran.rst @@ -222,7 +222,7 @@ The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong, Ireland, Nigeria, South Africa. The CCIR - N uses the PAL colorsystem and PAL frame size but the NTSC framerate, -and is used in Argentina, Uruguay, an a few others +and is used in Argentina, Uruguay, and a few others We do not talk about how the audio is broadcast ! From 96c1f4517eb4feeae4656cf018a8d8a6156f1db3 Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Sun, 5 Apr 2026 20:03:23 -0700 Subject: [PATCH 146/162] docs: fix typos and duplicated words across documentation Fix the following typos and duplicated words: - admin-guide/pm/intel-speed-select.rst: "weather" -> "whether" - core-api/real-time/differences.rst: "the the" -> "the" - admin-guide/bcache.rst: "to to" -> "to" Signed-off-by: Manuel Cortez Acked-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260406030323.1196-1-mdjesuscv@gmail.com> --- Documentation/admin-guide/bcache.rst | 2 +- Documentation/admin-guide/pm/intel-speed-select.rst | 2 +- Documentation/core-api/real-time/differences.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/admin-guide/bcache.rst b/Documentation/admin-guide/bcache.rst index f71f349553e4..325816edbdab 100644 --- a/Documentation/admin-guide/bcache.rst +++ b/Documentation/admin-guide/bcache.rst @@ -618,7 +618,7 @@ cache_replacement_policy One of either lru, fifo or random. freelist_percent - Size of the freelist as a percentage of nbuckets. Can be written to to + Size of the freelist as a percentage of nbuckets. Can be written to increase the number of buckets kept on the freelist, which lets you artificially reduce the size of the cache at runtime. Mostly for testing purposes (i.e. testing how different size caches affect your hit rate). diff --git a/Documentation/admin-guide/pm/intel-speed-select.rst b/Documentation/admin-guide/pm/intel-speed-select.rst index a2bfb971654f..dec2a25f10bc 100644 --- a/Documentation/admin-guide/pm/intel-speed-select.rst +++ b/Documentation/admin-guide/pm/intel-speed-select.rst @@ -287,7 +287,7 @@ level. Check presence of other Intel(R) SST features --------------------------------------------- -Each of the performance profiles also specifies weather there is support of +Each of the performance profiles also specifies whether there is support of other two Intel(R) SST features (Intel(R) Speed Select Technology - Base Frequency (Intel(R) SST-BF) and Intel(R) Speed Select Technology - Turbo Frequency (Intel SST-TF)). diff --git a/Documentation/core-api/real-time/differences.rst b/Documentation/core-api/real-time/differences.rst index 83ec9aa1c61a..a129570dab5a 100644 --- a/Documentation/core-api/real-time/differences.rst +++ b/Documentation/core-api/real-time/differences.rst @@ -213,7 +213,7 @@ to suspend until the callback completes, ensuring forward progress without risking livelock. In order to solve the problem at the API level, the sequence locks were extended -to allow a proper handover between the the spinning reader and the maybe +to allow a proper handover between the spinning reader and the maybe blocked writer. Sequence locks From ba716ad46d251528562fdd65cad8ce0b09853bd2 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Sun, 5 Apr 2026 19:38:45 +0300 Subject: [PATCH 147/162] Documentation/rtla: Convert links to RST format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Web links in the documentation are not properly displayed. In the man pages web links look like: Osnoise tracer documentation: < > On web pages the URL caption is the URL itself. Convert tracer documentation links to RST anonymous hyperlink format for better rendering. Use newer docs.kernel.org instead of www.kernel.org/doc/html/latest for brevity. After the change, the links in the man pages look like: Osnoise tracer On web pages the captions are the titles of the links. Signed-off-by: Costa Shulyupin Signed-off-by: Jonathan Corbet Message-ID: <20260405163847.3337981-1-costa.shul@redhat.com> --- Documentation/tools/rtla/rtla-hwnoise.rst | 2 +- Documentation/tools/rtla/rtla-osnoise-hist.rst | 2 +- Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +- Documentation/tools/rtla/rtla-osnoise.rst | 2 +- Documentation/tools/rtla/rtla-timerlat-hist.rst | 2 +- Documentation/tools/rtla/rtla-timerlat-top.rst | 2 +- Documentation/tools/rtla/rtla-timerlat.rst | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/tools/rtla/rtla-hwnoise.rst b/Documentation/tools/rtla/rtla-hwnoise.rst index 26512b15fe7b..5930bbca4522 100644 --- a/Documentation/tools/rtla/rtla-hwnoise.rst +++ b/Documentation/tools/rtla/rtla-hwnoise.rst @@ -100,7 +100,7 @@ SEE ALSO **rtla-osnoise**\(1) -Osnoise tracer documentation: +`Osnoise tracer `__ AUTHOR ====== diff --git a/Documentation/tools/rtla/rtla-osnoise-hist.rst b/Documentation/tools/rtla/rtla-osnoise-hist.rst index 007521c865d9..6ddea2c6d490 100644 --- a/Documentation/tools/rtla/rtla-osnoise-hist.rst +++ b/Documentation/tools/rtla/rtla-osnoise-hist.rst @@ -59,7 +59,7 @@ SEE ALSO ======== **rtla-osnoise**\(1), **rtla-osnoise-top**\(1) -*osnoise* tracer documentation: +`Osnoise tracer `__ AUTHOR ====== diff --git a/Documentation/tools/rtla/rtla-osnoise-top.rst b/Documentation/tools/rtla/rtla-osnoise-top.rst index 6ccadae38945..b91c02ac2bbe 100644 --- a/Documentation/tools/rtla/rtla-osnoise-top.rst +++ b/Documentation/tools/rtla/rtla-osnoise-top.rst @@ -54,7 +54,7 @@ SEE ALSO **rtla-osnoise**\(1), **rtla-osnoise-hist**\(1) -Osnoise tracer documentation: +`Osnoise tracer `__ AUTHOR ====== diff --git a/Documentation/tools/rtla/rtla-osnoise.rst b/Documentation/tools/rtla/rtla-osnoise.rst index 540d2bf6c152..decd9e11fcf2 100644 --- a/Documentation/tools/rtla/rtla-osnoise.rst +++ b/Documentation/tools/rtla/rtla-osnoise.rst @@ -50,7 +50,7 @@ SEE ALSO ======== **rtla-osnoise-top**\(1), **rtla-osnoise-hist**\(1) -Osnoise tracer documentation: +`Osnoise tracer `__ AUTHOR ====== diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentation/tools/rtla/rtla-timerlat-hist.rst index f56fe546411b..dab75677b06e 100644 --- a/Documentation/tools/rtla/rtla-timerlat-hist.rst +++ b/Documentation/tools/rtla/rtla-timerlat-hist.rst @@ -104,7 +104,7 @@ SEE ALSO ======== **rtla-timerlat**\(1), **rtla-timerlat-top**\(1) -*timerlat* tracer documentation: +`Timerlat tracer `__ AUTHOR ====== diff --git a/Documentation/tools/rtla/rtla-timerlat-top.rst b/Documentation/tools/rtla/rtla-timerlat-top.rst index 72d85e36c193..05959f1a4661 100644 --- a/Documentation/tools/rtla/rtla-timerlat-top.rst +++ b/Documentation/tools/rtla/rtla-timerlat-top.rst @@ -127,7 +127,7 @@ SEE ALSO -------- **rtla-timerlat**\(1), **rtla-timerlat-hist**\(1) -*timerlat* tracer documentation: +`Timerlat tracer `__ AUTHOR ------ diff --git a/Documentation/tools/rtla/rtla-timerlat.rst b/Documentation/tools/rtla/rtla-timerlat.rst index ce9f57e038c3..63718c52aa3f 100644 --- a/Documentation/tools/rtla/rtla-timerlat.rst +++ b/Documentation/tools/rtla/rtla-timerlat.rst @@ -45,7 +45,7 @@ SEE ALSO ======== **rtla-timerlat-top**\(1), **rtla-timerlat-hist**\(1) -*timerlat* tracer documentation: +`Timerlat tracer `__ AUTHOR ====== From 1cc973b7c94a77bd3419bca847bbf19b5cfdfa4c Mon Sep 17 00:00:00 2001 From: fangqiurong Date: Fri, 3 Apr 2026 13:58:06 +0800 Subject: [PATCH 148/162] sched/doc: Update yield_task description in sched-design-CFS The yield_task description referenced the long-removed compat_yield sysctl and described the function as a dequeue/enqueue cycle. Update it to reflect current behavior: yielding the CPU by moving the current task's position back in the runqueue. Sync zh_CN and sp_SP translations. Signed-off-by: fangqiurong Signed-off-by: Jonathan Corbet Message-ID: <20260403055806.358921-1-user@fqr-pc> --- Documentation/scheduler/sched-design-CFS.rst | 5 ++--- .../translations/sp_SP/scheduler/sched-design-CFS.rst | 6 +++--- .../translations/zh_CN/scheduler/sched-design-CFS.rst | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Documentation/scheduler/sched-design-CFS.rst b/Documentation/scheduler/sched-design-CFS.rst index b574a2644c77..03998f6c8f9c 100644 --- a/Documentation/scheduler/sched-design-CFS.rst +++ b/Documentation/scheduler/sched-design-CFS.rst @@ -183,9 +183,8 @@ This is the (partial) list of the hooks: - yield_task(...) - This function is basically just a dequeue followed by an enqueue, unless the - compat_yield sysctl is turned on; in that case, it places the scheduling - entity at the right-most end of the red-black tree. + This function yields the CPU by moving the currently running task's position back + in the runqueue, so that other runnable tasks get scheduled first. - wakeup_preempt(...) diff --git a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst index b35d24464be9..ff0ccbc59183 100644 --- a/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst +++ b/Documentation/translations/sp_SP/scheduler/sched-design-CFS.rst @@ -198,9 +198,9 @@ Esta es la lista parcial de llamadas: - yield_task(...) - Esta función es básicamente desencolar, seguido por encolar, a menos que - sysctl compat_yield esté activado; en ese caso, sitúa la entidad a gestionar - en la parte más hacia la derecha del árbol rojo-negro. + Esta función cede la CPU desplazando la posición de la tarea actualmente + en ejecución hacia atrás en la cola de ejecución, para que otras tareas + ejecutables sean planificadas primero. - check_preempt_curr(...) diff --git a/Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst b/Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst index abc6709ec3b2..03691e0309af 100644 --- a/Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst +++ b/Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst @@ -144,8 +144,8 @@ array)。 - yield_task(...) - 这个函数的行为基本上是出队,紧接着入队,除非compat_yield sysctl被开启。在那种情况下, - 它将调度实体放在红黑树的最右端。 + 此函数通过将当前任务在运行队列中的位置后移来让出 CPU, + 使得其他可运行的任务优先被调度。 - wakeup_preempt(...) From 15d49089e5b541c514fa458d6c8487afc8f8af7c Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Mon, 30 Mar 2026 06:59:57 -0400 Subject: [PATCH 149/162] Documentation/kernel-parameters: fix architecture alignment for pt, nopt, and nobypass Commit ab0e7f20768a ("Documentation: Merge x86-specific boot options doc into kernel-parameters.txt") introduced a formatting regression where architecture tags were placed on separate lines with broken indentation. This caused the 'nopt' [X86] parameter to appear as if it belonged to the [PPC/POWERNV] section. Furthermore, since the main 'iommu=' parameter heading already specifies it is for [X86, EARLY], the subsequent standalone [X86] tags for 'pt', 'nopt', and the AMD GART options are redundant and clutter the documentation. Clean up the formatting by removing these redundant tags and properly attributing the 'nobypass' option to [PPC/POWERNV]. Fixes: ab0e7f20768a ("Documentation: Merge x86-specific boot options doc into kernel-parameters.txt") Acked-by: Randy Dunlap Signed-off-by: Li RongQing Signed-off-by: Jonathan Corbet Message-ID: <20260330105957.2271-1-lirongqing@baidu.com> --- Documentation/admin-guide/kernel-parameters.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index c3460c920f84..b88b5f74d527 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2614,15 +2614,11 @@ Kernel parameters Intel machines). This can be used to prevent the usage of an available hardware IOMMU. - [X86] pt - [X86] nopt - [PPC/POWERNV] - nobypass + nobypass [PPC/POWERNV] Disable IOMMU bypass, using IOMMU for PCI devices. - [X86] AMD Gart HW IOMMU-specific options: From c41d03d03fe95f9f81fcb519d1f934e48e168c29 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Mar 2026 16:09:34 -0700 Subject: [PATCH 150/162] Docs: hid: intel-ish-hid: make long URL usable The '\' line continuation character in this long URL doesn't help anything. There is no documentation tooling that handles the line continuation character to join the 2 lines to make a usable URL. Web browsers terminate the URL just before the '\' character so that the second line of the URL is lost. See: https://docs.kernel.org/hid/intel-ish-hid.html Join the 2 lines together so that the URL is usable. Signed-off-by: Randy Dunlap Signed-off-by: Jonathan Corbet Message-ID: <20260321230934.435020-1-rdunlap@infradead.org> --- Documentation/hid/intel-ish-hid.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/hid/intel-ish-hid.rst b/Documentation/hid/intel-ish-hid.rst index 068a5906b177..21500c1cc1fe 100644 --- a/Documentation/hid/intel-ish-hid.rst +++ b/Documentation/hid/intel-ish-hid.rst @@ -163,8 +163,8 @@ The transport layer is a bi-directional protocol, which defines: - A flow control mechanism to avoid buffer overflows This protocol resembles bus messages described in the following document: -http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ -specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" +http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/dcmi-hi-1-0-spec.pdf +"Chapter 7: Bus Message Layer". Connection and Flow Control Mechanism ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 136799e52c4d3ebf14705ffffb69b8c7ae6f03ae Mon Sep 17 00:00:00 2001 From: Shubham Chakraborty Date: Wed, 4 Mar 2026 20:34:19 +0530 Subject: [PATCH 151/162] docs: sysctl: Add documentation for /proc/sys/xen/ Add documentation for the Xen hypervisor sysctl controls in /proc/sys/xen/balloon/. Documents the hotplug_unpopulated tunable (available when CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is enabled) which controls whether unpopulated memory regions are automatically hotplugged when the Xen balloon driver needs to reclaim memory. The documentation is based on source code analysis of drivers/xen/balloon.c. Signed-off-by: Shubham Chakraborty Signed-off-by: Jonathan Corbet Message-ID: <20260304150419.16738-1-chakrabortyshubham66@gmail.com> --- Documentation/admin-guide/sysctl/index.rst | 3 ++- Documentation/admin-guide/sysctl/xen.rst | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Documentation/admin-guide/sysctl/xen.rst diff --git a/Documentation/admin-guide/sysctl/index.rst b/Documentation/admin-guide/sysctl/index.rst index e153c96119df..50f00514f0ff 100644 --- a/Documentation/admin-guide/sysctl/index.rst +++ b/Documentation/admin-guide/sysctl/index.rst @@ -84,7 +84,7 @@ sunrpc/ SUN Remote Procedure Call (NFS) user/ Per user namespace limits vm/ memory management tuning buffer and cache management -xen/ +xen/ Xen hypervisor controls =============== =============================================================== These are the subdirs I have on my system or have been discovered by @@ -104,3 +104,4 @@ it :-) sunrpc user vm + xen diff --git a/Documentation/admin-guide/sysctl/xen.rst b/Documentation/admin-guide/sysctl/xen.rst new file mode 100644 index 000000000000..6c5edc3e5e4c --- /dev/null +++ b/Documentation/admin-guide/sysctl/xen.rst @@ -0,0 +1,31 @@ +=============== +/proc/sys/xen/ +=============== + +Copyright (c) 2026, Shubham Chakraborty + +For general info and legal blurb, please look in +Documentation/admin-guide/sysctl/index.rst. + +------------------------------------------------------------------------------ + +These files show up in ``/proc/sys/xen/``, depending on the +kernel configuration: + +.. contents:: :local: + +balloon/hotplug_unpopulated +=========================== + +This flag controls whether unpopulated memory ranges are automatically +hotplugged as system RAM. + +- ``0``: Unpopulated ranges are not hotplugged (default). +- ``1``: Unpopulated ranges are automatically hotplugged. + +When enabled, the Xen balloon driver will add memory regions that are +marked as unpopulated in the Xen memory map to the system as usable RAM. +This allows for dynamic memory expansion in Xen guest domains. + +This option is only available when the kernel is built with +``CONFIG_XEN_BALLOON_MEMORY_HOTPLUG`` enabled. From 1eab6493f525910aa7bc383a2a27b68916e3c616 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 26 Jan 2026 18:17:42 -0500 Subject: [PATCH 152/162] tracing: Documentation: Update histogram-design.rst for fn() handling The histogram documentation describes the old method of the histogram triggers using the fn() field of the histogram field structure to process the field. But due to Spectre mitigation, the function pointer to handle the fields at runtime caused a noticeable overhead. It was converted over to a fn_num and hist_fn_call() is now used to call the specific functions for the fields via a switch statement based on the field's fn_num value. Update the documentation to reflect this change. Signed-off-by: Steven Rostedt (Google) Signed-off-by: Jonathan Corbet Message-ID: <20260126181742.03e8f0d5@gandalf.local.home> --- Documentation/trace/histogram-design.rst | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Documentation/trace/histogram-design.rst b/Documentation/trace/histogram-design.rst index ae71b5bf97c6..e92f56ebd0b5 100644 --- a/Documentation/trace/histogram-design.rst +++ b/Documentation/trace/histogram-design.rst @@ -69,7 +69,8 @@ So in this histogram, there's a separate bucket for each pid, and each bucket contains a value for that bucket, counting the number of times sched_waking was called for that pid. -Each histogram is represented by a hist_data struct. +Each histogram is represented by a hist_data struct +(struct hist_trigger_data). To keep track of each key and value field in the histogram, hist_data keeps an array of these fields named fields[]. The fields[] array is @@ -82,7 +83,7 @@ value or not, which the above histogram does not. Each struct hist_field contains a pointer to the ftrace_event_field from the event's trace_event_file along with various bits related to -that such as the size, offset, type, and a hist_field_fn_t function, +that such as the size, offset, type, and a hist field function, which is used to grab the field's data from the ftrace event buffer (in most cases - some hist_fields such as hitcount don't directly map to an event field in the trace buffer - in these cases the function @@ -241,28 +242,33 @@ it, event_hist_trigger() is called. event_hist_trigger() first deals with the key: for each subkey in the key (in the above example, there is just one subkey corresponding to pid), the hist_field that represents that subkey is retrieved from hist_data.fields[] and the -hist_field_fn_t fn() associated with that field, along with the +hist field function associated with that field, along with the field's size and offset, is used to grab that subkey's data from the current trace record. +Note, the hist field function use to be a function pointer in the +hist_field stucture. Due to spectre mitigation, it was converted into +a fn_num and hist_fn_call() is used to call the associated hist field +function that corresponds to the fn_num of the hist_field structure. + Once the complete key has been retrieved, it's used to look that key up in the tracing_map. If there's no tracing_map_elt associated with that key, an empty one is claimed and inserted in the map for the new key. In either case, the tracing_map_elt associated with that key is returned. -Once a tracing_map_elt available, hist_trigger_elt_update() is called. +Once a tracing_map_elt is available, hist_trigger_elt_update() is called. As the name implies, this updates the element, which basically means updating the element's fields. There's a tracing_map_field associated with each key and value in the histogram, and each of these correspond to the key and value hist_fields created when the histogram was created. hist_trigger_elt_update() goes through each value hist_field -and, as for the keys, uses the hist_field's fn() and size and offset +and, as for the keys, uses the hist_field's function and size and offset to grab the field's value from the current trace record. Once it has that value, it simply adds that value to that field's continually-updated tracing_map_field.sum member. Some hist_field -fn()s, such as for the hitcount, don't actually grab anything from the -trace record (the hitcount fn() just increments the counter sum by 1), +functions, such as for the hitcount, don't actually grab anything from the +trace record (the hitcount function just increments the counter sum by 1), but the idea is the same. Once all the values have been updated, hist_trigger_elt_update() is From 29442165759cd557194815cdba391a4bf37db05e Mon Sep 17 00:00:00 2001 From: LIU Haoyang Date: Fri, 6 Mar 2026 04:10:58 +0800 Subject: [PATCH 153/162] docs/zh_CN: fix an inconsistent statement in dev-tools/testing-overview This patch fixes an inconsistent describtion in testing-overview.rst, which should be ``kmalloc`` instead of ``kmalloc_arry`` according to the original text. Signed-off-by: LIU Haoyang Reviewed-by: Dongliang Mu Signed-off-by: Alex Shi --- Documentation/translations/zh_CN/dev-tools/testing-overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/translations/zh_CN/dev-tools/testing-overview.rst b/Documentation/translations/zh_CN/dev-tools/testing-overview.rst index 286ed6b01f65..8bdc51b47b5e 100644 --- a/Documentation/translations/zh_CN/dev-tools/testing-overview.rst +++ b/Documentation/translations/zh_CN/dev-tools/testing-overview.rst @@ -154,7 +154,7 @@ Smatch和Coccinelle的强项 Coccinelle可能是最容易写检查的。它在预处理器之前工作,所以用Coccinelle 检查宏中的错误更容易。Coccinelle还能为你创建补丁,这是其他工具无法做到的。 -例如,用Coccinelle你可以从 ``kmalloc_array(x, size, GFP_KERNEL)`` +例如,用Coccinelle你可以从 ``kmalloc(x * size, GFP_KERNEL)`` 到 ``kmalloc_array(x, size, GFP_KERNEL)`` 进行大规模转换,这真的很 有用。如果你只是创建一个Smatch警告,并试图把转换的工作推给维护者,他们会很 恼火。你将不得不为每个警告争论是否真的可以溢出。 From 8c199fb49871cad666e408af41ca3c145679b8a4 Mon Sep 17 00:00:00 2001 From: Song Hongyi Date: Wed, 11 Mar 2026 20:31:03 +0800 Subject: [PATCH 154/162] docs/zh_CN: sync process/2.Process.rst with English version The Chinese translation of the development process documentation was outdated. Sync it with the current English version to ensure consistency. Key changes include: - Update versioning examples from 5.x to the 9.x placeholder. - Add footnote [1] to explain the non-semantic versioning scheme. - Replace the obsolete LTS kernel table with a link to kernel.org. - Add a cross-reference for the "interleaved replies" section. Update the translation through commit 5ce70894f6ca ("Doc: correct spelling and wording mistakes") Signed-off-by: Song Hongyi Signed-off-by: Alex Shi --- .../translations/zh_CN/process/2.Process.rst | 52 ++++++++----------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/Documentation/translations/zh_CN/process/2.Process.rst b/Documentation/translations/zh_CN/process/2.Process.rst index 31b0e2c994f6..ca00672c313e 100644 --- a/Documentation/translations/zh_CN/process/2.Process.rst +++ b/Documentation/translations/zh_CN/process/2.Process.rst @@ -23,21 +23,18 @@ 总览 ---- -内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要 -内核版本。最近的发布历史记录如下: +内核开发使用一个松散的、基于时间的滚动发布(rolling release)开发模型。 +一个新的主内核发行版本(作为示例,我们将其称为 9.x) [1]_ 大约每两到三个月 +发布一次,它带来了新特性、内部 API 的更改等。一个典型的版本包含大约 13,000 +个变更集(changesets),涉及几十万行代码的修改。最近的发行版本及其日期可以 +在这里找到 +`维基百科 `_ - ====== ================= - 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内核开发的前 -沿;内核使用滚动开发模型,不断集成重大变化。 +.. [1] 严格来说,Linux 内核并不采用语义化版本号方案,而是将 9.x 这一组数字 + 作为一个整体来标识主发行版本号。对于每一个版本,x 都会递增,但只有 + 当 x 被认为足够大时,9 才会递增(例如:Linux 5.0 是紧随 Linux 4.20 + 之后发布的)。 对于每个版本的补丁合并,遵循一个相对简单的规则。在每个开发周期的开头,“合并 窗口”被打开。这时,被认为足够稳定(并且被开发社区接受)的代码被合并到主线内 @@ -48,8 +45,8 @@ 提前收集、测试和分级的。稍后将详细描述该过程的工作方式。) 合并窗口持续大约两周。在这段时间结束时,Linus Torvalds将声明窗口已关闭,并 -释放第一个“rc”内核。例如,对于目标为5.6的内核,在合并窗口结束时发生的释放 -将被称为5.6-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一 +释放第一个“rc”内核。例如,对于目标为9.x的内核,在合并窗口结束时发生的释放 +将被称为9.x-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一 个内核的时间已经到来。 在接下来的6到10周内,只有修复问题的补丁才应该提交给主线。有时会允许更大的 @@ -84,11 +81,14 @@ 开发人员的目标是在稳定发布之前修复所有已知的回归。在现实世界中,这种完美是 很难实现的;在这种规模的项目中,变数太多了。需要说明的是,延迟最终版本只会 使问题变得更糟;等待下一个合并窗口的更改将变多,导致下次出现更多的回归错误。 -因此,大多数5.x内核都有一些已知的回归错误,不过,希望没有一个是严重的。 +因此,大多数内核发布时都会带有一部分已知的回归问题,不过希望它们都不是严重 +的问题。 一旦一个稳定的版本发布,它的持续维护工作就被移交给“稳定团队”,目前由 -Greg Kroah-Hartman领导。稳定团队将使用5.x.y编号方案不定期地发布稳定版本的 -更新。要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到 +Greg Kroah-Hartman领导。稳定团队将使用9.x.y编号方案不定期地发布稳定版本的 +更新。 + +要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到 下一个开发版本主线中。内核通常会在其初始版本后的一个以上的开发周期内收到 稳定版更新。例如,5.2内核的历史如下(2019年): @@ -105,17 +105,10 @@ Greg Kroah-Hartman领导。稳定团队将使用5.x.y编号方案不定期地发 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 - ====== ================================ ================ + https://www.kernel.org/category/releases.html 长期支持内核的选择纯粹是维护人员是否有需求和时间来维护该版本的问题。 目前还没有为即将发布的任何特定版本提供长期支持的已知计划。 @@ -320,7 +313,8 @@ Quilt 是一个补丁管理系统,而不是源代码管理系统。它不会 没有完成家庭作业的人感到不耐烦。 - 避免顶部回复(把你的答案放在你要回复的引文上面的做法)。这会让你的回答更难 - 理解,印象也很差。 + 理解,印象也很差,详细请查看 + :ref:`Documentation/process/submitting-patches.rst ` - 在正确的邮件列表发问。linux-kernel 可能是通用的讨论场所,但它不是寻找所有 子系统开发人员的最佳场所。 From 4c361fc63d89cd2f8ca1a49d2c552664ed1793c1 Mon Sep 17 00:00:00 2001 From: Ben Guo Date: Fri, 10 Apr 2026 10:41:10 +0800 Subject: [PATCH 155/162] docs/zh_CN: update rust/arch-support.rst translation Update the translation of .../rust/arch-support.rst into Chinese. Update the translation through commit ccb8ce526807 ("ARM: 9441/1: rust: Enable Rust support for ARMv7") Reviewed-by: Dongliang Mu Reviewed-by: Gary Guo Signed-off-by: Ben Guo Signed-off-by: Alex Shi --- Documentation/translations/zh_CN/rust/arch-support.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/translations/zh_CN/rust/arch-support.rst b/Documentation/translations/zh_CN/rust/arch-support.rst index abd708d48f82..f5ae44588a57 100644 --- a/Documentation/translations/zh_CN/rust/arch-support.rst +++ b/Documentation/translations/zh_CN/rust/arch-support.rst @@ -19,9 +19,10 @@ ============= ================ ============================================== 架构 支持水平 限制因素 ============= ================ ============================================== -``arm64`` Maintained 只有小端序 +``arm`` Maintained 仅 ARMv7 小端序。 +``arm64`` Maintained 仅小端序。 ``loongarch`` Maintained \- -``riscv`` Maintained 只有 ``riscv64`` -``um`` Maintained 只有 ``x86_64`` -``x86`` Maintained 只有 ``x86_64`` +``riscv`` Maintained 仅 ``riscv64``,且仅限 LLVM/Clang。 +``um`` Maintained \- +``x86`` Maintained 仅 ``x86_64``。 ============= ================ ============================================== From a32ee1a808fe7dd9c3fa48d2af83334d47e76b78 Mon Sep 17 00:00:00 2001 From: Ben Guo Date: Fri, 10 Apr 2026 10:41:11 +0800 Subject: [PATCH 156/162] docs/zh_CN: update rust/coding-guidelines.rst translation Update the translation of .../rust/coding-guidelines.rst into Chinese. Update the translation through commit 4a9cb2eecc78 ("docs: rust: add section on imports formatting") Reviewed-by: Dongliang Mu Reviewed-by: Gary Guo Signed-off-by: Ben Guo Signed-off-by: Alex Shi --- .../zh_CN/rust/coding-guidelines.rst | 262 +++++++++++++++++- 1 file changed, 248 insertions(+), 14 deletions(-) diff --git a/Documentation/translations/zh_CN/rust/coding-guidelines.rst b/Documentation/translations/zh_CN/rust/coding-guidelines.rst index 419143b938ed..54b902322dbc 100644 --- a/Documentation/translations/zh_CN/rust/coding-guidelines.rst +++ b/Documentation/translations/zh_CN/rust/coding-guidelines.rst @@ -37,6 +37,73 @@ 像内核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在单个文件上工作,并且不需要 内核配置。有时,它甚至可以与破碎的代码一起工作。 +导入 +~~~~ + +``rustfmt`` 默认会以一种在合并和变基时容易产生冲突的方式格式化导入,因为在某些情况下 +它会将多个条目合并到同一行。例如: + +.. code-block:: rust + + // Do not use this style. + use crate::{ + example1, + example2::{example3, example4, example5}, + example6, example7, + example8::example9, + }; + +相反,内核使用如下所示的垂直布局: + +.. code-block:: rust + + use crate::{ + example1, + example2::{ + example3, + example4, + example5, // + }, + example6, + example7, + example8::example9, // + }; + +也就是说,每个条目占一行,只要列表中有多个条目就使用花括号。 + +末尾的空注释可以保留这种格式。不仅如此, ``rustfmt`` 在添加空注释后实际上会将导入重 +新格式化为垂直布局。也就是说,可以通过对如下输入运行 ``rustfmt`` 来轻松地将原始示例 +重新格式化为预期的风格: + +.. code-block:: rust + + // Do not use this style. + use crate::{ + example1, + example2::{example3, example4, example5, // + }, + example6, example7, + example8::example9, // + }; + +末尾的空注释适用于嵌套导入(如上所示)以及单条目导入——这有助于最小化补丁系列中的差 +异: + +.. code-block:: rust + + use crate::{ + example1, // + }; + +末尾的空注释可以放在花括号内的任何一行中,但建议放在最后一个条目上,因为这让人联想到其 +他格式化工具中的末尾逗号。有时在补丁系列中由于列表的变更,避免多次移动注释可能更简单。 + +在某些情况下可能需要例外处理,即以上都不是硬性规则。也有一些代码尚未迁移到这种风格,但 +请不要引入其他风格的代码。 + +最终目标是让 ``rustfmt`` 在稳定版本中自动支持这种格式化风格(或类似的风格),而无需 +末尾的空注释。因此,在某个时候,目标是移除这些注释。 + 注释 ---- @@ -77,6 +144,16 @@ // ... } +这适用于公共和私有项目。这增加了与公共项目的一致性,允许在更改可见性时减少涉及的更改, +并允许我们将来也为私有项目生成文档。换句话说,如果为私有项目编写了文档,那么仍然应该使 +用 ``///`` 。例如: + +.. code-block:: rust + + /// My private function. + // TODO: ... + fn f() {} + 一种特殊的注释是 ``// SAFETY:`` 注释。这些注释必须出现在每个 ``unsafe`` 块之前,它们 解释了为什么该块内的代码是正确/健全的,即为什么它在任何情况下都不会触发未定义行为,例如: @@ -131,27 +208,27 @@ https://commonmark.org/help/ 这个例子展示了一些 ``rustdoc`` 的特性和内核中遵循的一些惯例: - - 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额 - 外的段落中。 +- 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额 + 外的段落中。 - - 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。 +- 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。 - - 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发 - 生这种情况的条件。 +- 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发 + 生这种情况的条件。 - 请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下, - 都应该使用一个可失败的方法,通常是返回一个 ``Result``。 + 请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下, + 都应该使用一个可失败的方法,通常是返回一个 ``Result``。 - - 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。 +- 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。 - - Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个 - 链接)。 +- Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个 + 链接)。 - - 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面 - 的代码为什么是正确的。 +- 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面 + 的代码为什么是正确的。 - 虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法, - 最重要的是,它提供了一种知道没有额外隐含约束的方法。 + 虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法, + 最重要的是,它提供了一种知道没有额外隐含约束的方法。 要了解更多关于如何编写Rust和拓展功能的文档,请看看 ``rustdoc`` 这本书,网址是: @@ -170,6 +247,22 @@ https://commonmark.org/help/ /// [`struct mutex`]: srctree/include/linux/mutex.h +C FFI 类型 +---------- + +Rust 内核代码使用类型别名(如 ``c_int``)来引用 C 类型(如 ``int``),这些别名可 +以直接从 ``kernel`` 预导入(prelude)中获取。请不要使用 ``core::ffi`` 中的别 +名——它们可能无法映射到正确的类型。 + +这些别名通常应该直接通过其标识符引用,即作为单段路径。例如: + +.. code-block:: rust + + fn f(p: *const c_char) -> c_int { + // ... + } + + 命名 ---- @@ -202,3 +295,144 @@ Rust内核代码遵循通常的Rust命名空间: 也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。 特别是,它不应该被命名为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。 + + +代码检查提示(Lints) +--------------------- + +在 Rust 中,可以在局部 ``allow`` 特定的警告(诊断信息、代码检查提示(lint)), +使编译器忽略给定函数、模块、代码块等中给定警告的实例。 + +这类似于 C 中的 ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` +[#]_: + +.. code-block:: c + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-function" + static void f(void) {} + #pragma GCC diagnostic pop + +.. [#] 在这个特定情况下,可以使用内核的 ``__{always,maybe}_unused`` 属性 + (C23 的 ``[[maybe_unused]]``);然而,此示例旨在反映下文讨论的 Rust 中 + 的等效代码检查提示。 + +但要简洁得多: + +.. code-block:: rust + + #[allow(dead_code)] + fn f() {} + +凭借这一点,可以更方便地默认启用更多诊断(即在 ``W=`` 级别之外)。特别是那些可能有 +一些误报但在其他方面非常有用的诊断,保持启用可以捕获潜在的错误。 + +在此基础上,Rust 提供了 ``expect`` 属性,更进一步。如果警告没有产生,它会让编译器 +发出警告。例如,以下代码将确保当 ``f()`` 在某处被调用时,我们必须移除该属性: + +.. code-block:: rust + + #[expect(dead_code)] + fn f() {} + +如果我们不这样做,编译器会发出警告:: + + warning: this lint expectation is unfulfilled + --> x.rs:3:10 + | + 3 | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +这意味着 ``expect`` 不会在不需要时被遗忘,这可能发生在以下几种情况中: + +- 开发过程中添加的临时属性。 + +- 编译器、Clippy 或自定义工具中代码检查提示的改进可能消除误报。 + +- 当代码检查提示不再需要时,因为预期它会在某个时候被移除,例如上面的 + ``dead_code`` 示例。 + +这也增加了剩余 ``allow`` 的可见性,并减少了误用的可能性。 + +因此,优先使用 ``expect`` 而不是 ``allow``,除非: + +- 条件编译在某些情况下触发警告,在其他情况下不触发。 + + 如果与总的相比,只有少数情况触发(或不触发)警告,那么可以考虑使用条件 + ``expect``(即 ``cfg_attr(..., expect(...))``)。否则,使用 ``allow`` 可 + 能更简单。 + +- 在宏内部,不同的调用可能会创建在某些情况下触发警告而在其他情况下不触发的展开代码。 + +- 当代码可能在某些架构上触发警告但在其他架构上不触发时,例如到 C FFI 类型的 ``as`` + 转换。 + +作为一个更详细的示例,考虑以下程序: + +.. code-block:: rust + + fn g() {} + + fn main() { + #[cfg(CONFIG_X)] + g(); + } + +这里,如果 ``CONFIG_X`` 未设置,函数 ``g()`` 是死代码。我们可以在这里使用 +``expect`` 吗? + +.. code-block:: rust + + #[expect(dead_code)] + fn g() {} + + fn main() { + #[cfg(CONFIG_X)] + g(); + } + +如果 ``CONFIG_X`` 被设置,这将产生代码检查提示,因为在该配置中它不是死代码。因 +此,在这种情况下,我们不能直接使用 ``expect``。 + +一个简单的可能性是使用 ``allow``: + +.. code-block:: rust + + #[allow(dead_code)] + fn g() {} + + fn main() { + #[cfg(CONFIG_X)] + g(); + } + +另一种方法是使用条件 ``expect``: + +.. code-block:: rust + + #[cfg_attr(not(CONFIG_X), expect(dead_code))] + fn g() {} + + fn main() { + #[cfg(CONFIG_X)] + g(); + } + +这将确保如果有人在某处引入了对 ``g()`` 的另一个调用(例如无条件的),那么将会被发现 +它不再是死代码。然而, ``cfg_attr`` 比简单的 ``allow`` 更复杂。 + +因此,当涉及多个配置或者代码检查提示可能由于非局部更改(如 ``dead_code``)而触发 +时,使用条件 ``expect`` 可能不值得。 + +有关 Rust 中诊断的更多信息,请参阅: + + https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html + +错误处理 +-------- + +有关 Rust for Linux 特定错误处理的背景和指南,请参阅: + + https://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust From 1e75555ee443b8d4c654535fa79435982c0b3722 Mon Sep 17 00:00:00 2001 From: Ben Guo Date: Fri, 10 Apr 2026 10:41:12 +0800 Subject: [PATCH 157/162] docs/zh_CN: update rust/quick-start.rst translation Update the translation of .../rust/quick-start.rst into Chinese. Update the translation through commit 5935461b4584 ("docs: rust: quick-start: add Debian 13 (Trixie)") Reviewed-by: Dongliang Mu Reviewed-by: Gary Guo Signed-off-by: Ben Guo Acked-by: Gary Guo # Rust Signed-off-by: Alex Shi --- .../translations/zh_CN/rust/quick-start.rst | 190 ++++++++++++++---- 1 file changed, 148 insertions(+), 42 deletions(-) diff --git a/Documentation/translations/zh_CN/rust/quick-start.rst b/Documentation/translations/zh_CN/rust/quick-start.rst index 8616556ae4d7..5f0ece6411f5 100644 --- a/Documentation/translations/zh_CN/rust/quick-start.rst +++ b/Documentation/translations/zh_CN/rust/quick-start.rst @@ -13,16 +13,138 @@ 本文介绍了如何开始使用Rust进行内核开发。 +安装内核开发所需的 Rust 工具链有几种方式。一种简单的方式是使用 Linux 发行版的软件包 +(如果它们合适的话)——下面的第一节解释了这种方法。这种方法的一个优势是,通常发行版会 +匹配 Rust 和 Clang 所使用的 LLVM。 + +另一种方式是使用 `kernel.org `_ 上提 +供的预构建稳定版本的 LLVM+Rust。这些与 :ref:`获取 LLVM ` 中的精 +简快速 LLVM 工具链相同,并添加了 Rust for Linux 支持的 Rust 版本。提供了两套工具 +链:"最新 LLVM" 和 "匹配 LLVM"(请参阅链接了解更多信息)。 + +或者,接下来的两个 "依赖" 章节将解释每个组件以及如何通过 ``rustup``、Rust 的独立 +安装程序或从源码构建来安装它们。 + +本文档的其余部分解释了有关如何入门的其他方面。 + + +发行版 +------ + +Arch Linux +********** + +Arch Linux 提供较新的 Rust 版本,因此通常开箱即用,例如:: + + pacman -S rust rust-src rust-bindgen + + +Debian +****** + +Debian 13(Trixie)以及 Testing 和 Debian Unstable(Sid)提供较新的 Rust 版 +本,因此通常开箱即用,例如:: + + apt install rustc rust-src bindgen rustfmt rust-clippy + + +Fedora Linux +************ + +Fedora Linux 提供较新的 Rust 版本,因此通常开箱即用,例如:: + + dnf install rust rust-src bindgen-cli rustfmt clippy + + +Gentoo Linux +************ + +Gentoo Linux(尤其是 testing 分支)提供较新的 Rust 版本,因此通常开箱即用, +例如:: + + USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen + +可能需要设置 ``LIBCLANG_PATH``。 + + +Nix +*** + +Nix(unstable 频道)提供较新的 Rust 版本,因此通常开箱即用,例如:: + + { pkgs ? import {} }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ rustc rust-bindgen rustfmt clippy ]; + RUST_LIB_SRC = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; + } + + +openSUSE +******** + +openSUSE Slowroll 和 openSUSE Tumbleweed 提供较新的 Rust 版本,因此通常开箱 +即用,例如:: + + zypper install rust rust1.79-src rust-bindgen clang + + +Ubuntu +****** + +25.04 +~~~~~ + +最新的 Ubuntu 版本提供较新的 Rust 版本,因此通常开箱即用,例如:: + + apt install rustc rust-src bindgen rustfmt rust-clippy + +此外,需要设置 ``RUST_LIB_SRC``,例如:: + + RUST_LIB_SRC=/usr/src/rustc-$(rustc --version | cut -d' ' -f2)/library + +为方便起见,可以将 ``RUST_LIB_SRC`` 导出到全局环境中。 + + +24.04 LTS 及更早版本 +~~~~~~~~~~~~~~~~~~~~ + +虽然 Ubuntu 24.04 LTS 及更早版本仍然提供较新的 Rust 版本,但它们需要一些额外的配 +置,使用带版本号的软件包,例如:: + + apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \ + rust-1.80-clippy + ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80 + ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80 + +这些软件包都不会将其工具设置为默认值;因此应该显式指定它们,例如:: + + make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \ + CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65 + +或者,修改 ``PATH`` 变量将 Rust 1.80 的二进制文件放在前面,并将 ``bindgen`` 设 +置为默认值,例如:: + + PATH=/usr/lib/rust-1.80/bin:$PATH + update-alternatives --install /usr/bin/bindgen bindgen \ + /usr/bin/bindgen-0.65 100 + update-alternatives --set bindgen /usr/bin/bindgen-0.65 + +使用带版本号的软件包时需要设置 ``RUST_LIB_SRC``,例如:: + + RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library + +为方便起见,可以将 ``RUST_LIB_SRC`` 导出到全局环境中。 + +此外, ``bindgen-0.65`` 在较新的版本(24.04 LTS 和 24.10)中可用,但在更早的版 +本(20.04 LTS 和 22.04 LTS)中可能不可用,因此可能需要手动构建 ``bindgen`` +(请参见下文)。 + 构建依赖 -------- 本节描述了如何获取构建所需的工具。 -其中一些依赖也许可以从Linux发行版中获得,包名可能是 ``rustc`` , ``rust-src`` , -``rust-bindgen`` 等。然而,在写这篇文章的时候,它们很可能还不够新,除非发行版跟踪最 -新的版本。 - 为了方便检查是否满足要求,可以使用以下目标:: make LLVM=1 rustavailable @@ -34,15 +156,14 @@ rustc ***** -需要一个特定版本的Rust编译器。较新的版本可能会也可能不会工作,因为就目前而言,内核依赖 -于一些不稳定的Rust特性。 +需要一个较新版本的Rust编译器。 如果使用的是 ``rustup`` ,请进入内核编译目录(或者用 ``--path=`` 参数 -来 ``设置`` sub-command)并运行:: +来 ``设置`` sub-command),例如运行:: - rustup override set $(scripts/min-tool-version.sh rustc) + rustup override set stable -+这将配置你的工作目录使用正确版本的 ``rustc``,而不影响你的默认工具链。 +这将配置你的工作目录使用给定版本的 ``rustc``,而不影响你的默认工具链。 请注意覆盖应用当前的工作目录(和它的子目录)。 @@ -54,7 +175,7 @@ rustc Rust标准库源代码 **************** -Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 和 ``alloc`` 。 +Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 。 如果正在使用 ``rustup`` ,请运行:: @@ -64,10 +185,10 @@ Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core 否则,如果使用独立的安装程序,可以将Rust源码树下载到安装工具链的文件夹中:: - curl -L "https://static.rust-lang.org/dist/rust-src-$(scripts/min-tool-version.sh rustc).tar.gz" | - tar -xzf - -C "$(rustc --print sysroot)/lib" \ - "rust-src-$(scripts/min-tool-version.sh rustc)/rust-src/lib/" \ - --strip-components=3 + curl -L "https://static.rust-lang.org/dist/rust-src-$(rustc --version | cut -d' ' -f2).tar.gz" | + tar -xzf - -C "$(rustc --print sysroot)/lib" \ + "rust-src-$(rustc --version | cut -d' ' -f2)/rust-src/lib/" \ + --strip-components=3 在这种情况下,以后升级Rust编译器版本需要手动更新这个源代码树(这可以通过移除 ``$(rustc --print sysroot)/lib/rustlib/src/rust`` ,然后重新执行上 @@ -97,24 +218,21 @@ Linux发行版中可能会有合适的包,所以最好先检查一下。 bindgen ******* -内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。这需要特定的版本。 +内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。 -通过以下方式安装它(注意,这将从源码下载并构建该工具):: +例如,通过以下方式安装它(注意,这将从源码下载并构建该工具):: - cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli + cargo install --locked bindgen-cli -``bindgen`` 需要找到合适的 ``libclang`` 才能工作。如果没有找到(或者找到的 -``libclang`` 与应该使用的 ``libclang`` 不同),则可以使用 ``clang-sys`` -理解的环境变量(Rust绑定创建的 ``bindgen`` 用来访问 ``libclang``): +``bindgen`` 使用 ``clang-sys`` crate 来查找合适的 ``libclang`` (可以静态链 +接、动态链接或在运行时加载)。默认情况下,上面的 ``cargo`` 命令会生成一个在运行时 +加载 ``libclang`` 的 ``bindgen`` 二进制文件。如果没有找到(或者应该使用与找到的 +不同的 ``libclang``),可以调整该过程,例如使用 ``LIBCLANG_PATH`` 环境变量。详 +情请参阅 ``clang-sys`` 的文档: + https://github.com/KyleMayes/clang-sys#linking -* ``LLVM_CONFIG_PATH`` 可以指向一个 ``llvm-config`` 可执行文件。 - -* 或者 ``LIBCLANG_PATH`` 可以指向 ``libclang`` 共享库或包含它的目录。 - -* 或者 ``CLANG_PATH`` 可以指向 ``clang`` 可执行文件。 - -详情请参阅 ``clang-sys`` 的文档: + https://github.com/KyleMayes/clang-sys#environment-variables 开发依赖 @@ -151,18 +269,6 @@ clippy 独立的安装程序也带有 ``clippy`` 。 -cargo -***** - -``cargo`` 是Rust的本地构建系统。目前需要它来运行测试,因为它被用来构建一个自定义的标准 -库,其中包含了内核中自定义 ``alloc`` 所提供的设施。测试可以使用 ``rusttest`` Make 目标 -来运行。 - -如果使用的是 ``rustup`` ,所有的配置文件都已经安装了该工具,因此不需要再做什么。 - -独立的安装程序也带有 ``cargo`` 。 - - rustdoc ******* @@ -223,7 +329,7 @@ Rust支持(CONFIG_RUST)需要在 ``General setup`` 菜单中启用。在其 如果使用的是GDB/Binutils,而Rust符号没有被demangled,原因是工具链还不支持Rust的新v0 mangling方案。有几个办法可以解决: - - 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。 +- 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。 - - 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``) - 中的pre-demangled的名字。 +- 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``) + 中的pre-demangled的名字。 From 78405e7f42fa9127325c65aec9289187f67ac5ce Mon Sep 17 00:00:00 2001 From: Ben Guo Date: Fri, 10 Apr 2026 10:41:13 +0800 Subject: [PATCH 158/162] docs/zh_CN: update rust/index.rst translation Update the translation of .../rust/index.rst into Chinese. Update the translation through commit a592a36e4937 ("Documentation: use a source-read extension for the index link boilerplate") Reviewed-by: Dongliang Mu Reviewed-by: Gary Guo Signed-off-by: Ben Guo Signed-off-by: Alex Shi --- Documentation/translations/zh_CN/rust/index.rst | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Documentation/translations/zh_CN/rust/index.rst b/Documentation/translations/zh_CN/rust/index.rst index 5347d4729588..138e057bee44 100644 --- a/Documentation/translations/zh_CN/rust/index.rst +++ b/Documentation/translations/zh_CN/rust/index.rst @@ -12,16 +12,6 @@ Rust 与内核中的Rust有关的文档。若要开始在内核中使用Rust,请阅读 quick-start.rst 指南。 -Rust 实验 ---------- -Rust 支持在 v6.1 版本中合并到主线,以帮助确定 Rust 作为一种语言是否适合内核, -即是否值得进行权衡。 - -目前,Rust 支持主要面向对 Rust 支持感兴趣的内核开发人员和维护者, -以便他们可以开始处理抽象和驱动程序,并帮助开发基础设施和工具。 - -如果您是终端用户,请注意,目前没有适合或旨在生产使用的内置驱动程序或模块, -并且 Rust 支持仍处于开发/实验阶段,尤其是对于特定内核配置。 代码文档 -------- @@ -50,10 +40,3 @@ Rust 支持在 v6.1 版本中合并到主线,以帮助确定 Rust 作为一种 testing 你还可以在 :doc:`../../../process/kernel-docs` 中找到 Rust 的学习材料。 - -.. only:: subproject and html - - Indices - ======= - - * :ref:`genindex` From 64cb68766fc8679626b422319b8b678d5792bfbf Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 10 Apr 2026 16:31:25 +0200 Subject: [PATCH 159/162] Documentation: seq_file: drop 2.6 reference Even kernels after 2.6 have seq-file support. Signed-off-by: Wolfram Sang Signed-off-by: Jonathan Corbet Message-ID: <20260410143234.43610-2-wsa+renesas@sang-engineering.com> --- Documentation/filesystems/seq_file.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/seq_file.rst b/Documentation/filesystems/seq_file.rst index 1e1713d00010..d753d8177bcb 100644 --- a/Documentation/filesystems/seq_file.rst +++ b/Documentation/filesystems/seq_file.rst @@ -27,7 +27,7 @@ position within the virtual file - that position is, likely as not, in the middle of a line of output. The kernel has traditionally had a number of implementations that got this wrong. -The 2.6 kernel contains a set of functions (implemented by Alexander Viro) +The kernel now contains a set of functions (implemented by Alexander Viro) which are designed to make it easy for virtual file creators to get it right. From bb6a85b4b652f8424b5a28c2c445ded41ded51d0 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 1 Apr 2026 13:02:32 +0200 Subject: [PATCH 160/162] Documentation: Add managed interrupts I stumbled upon "isolcpus=managed_irq" which is the last piece which can only be handled by isolcpus= and has no runtime knob. I knew roughly what managed interrupts should do but I lacked some details how it is used and what the managed_irq sub parameter means in practise. This documents what we have as of today and how it works. I added some examples how the parameter affects the configuration. Did I miss something? Given that the spreading as computed group_cpus_evenly() does not take the mask of isolated CPUs into account I'm not sure how relevant the managed_irq argument is. The virtio_scsi driver has no way to limit the interrupts and I don't see this for the nvme. Even if the number of queues can be reduced to two (as in the example) it is still spread evenly in the system instead and the isolated CPUs are not taken into account. To make this worse, you can even argue further whether or not the application on the isolated CPU wants to receive the interrupt directly or would prefer not to. Given all this, I am not sure if it makes sense to add 'io_queue' to the mix or if it could be incorporated into 'managed_irq'. One more point: Given that isolcpus= is marked deprecated as of commit b0d40d2b22fe4 ("sched/isolation: Document isolcpus= boot parameter flags, mark it deprecated") and the 'managed_irq' is evaluated at device's probe time it would require additional callbacks to re-evaluate the situation. Probably for 'io_queue', too. Does is make sense or should we simply drop the "deprecation" notice and allowing using it long term? Dynamic partitions work with cpusets, there this (managed_irq) limitation but is it really? And if static partition is the use case why bother. Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Ming Lei Reviewed-by: Aaron Tomlin Acked-by: Thomas Gleixner Signed-off-by: Jonathan Corbet Message-ID: <20260401110232.ET5RxZfl@linutronix.de> --- Documentation/core-api/irq/index.rst | 1 + Documentation/core-api/irq/managed_irq.rst | 116 +++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 Documentation/core-api/irq/managed_irq.rst diff --git a/Documentation/core-api/irq/index.rst b/Documentation/core-api/irq/index.rst index 0d65d11e5420..13bd24dd2b1c 100644 --- a/Documentation/core-api/irq/index.rst +++ b/Documentation/core-api/irq/index.rst @@ -9,3 +9,4 @@ IRQs irq-affinity irq-domain irqflags-tracing + managed_irq diff --git a/Documentation/core-api/irq/managed_irq.rst b/Documentation/core-api/irq/managed_irq.rst new file mode 100644 index 000000000000..05e295f3c289 --- /dev/null +++ b/Documentation/core-api/irq/managed_irq.rst @@ -0,0 +1,116 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================== +Affinity managed interrupts +=========================== + +The IRQ core provides support for managing interrupts according to a specified +CPU affinity. Under normal operation, an interrupt is associated with a +particular CPU. If that CPU is taken offline, the interrupt is migrated to +another online CPU. + +Devices with large numbers of interrupt vectors can stress the available vector +space. For example, an NVMe device with 128 I/O queues typically requests one +interrupt per queue on systems with at least 128 CPUs. Two such devices +therefore request 256 interrupts. On x86, the interrupt vector space is +notoriously low, providing only 256 vectors per CPU, and the kernel reserves a +subset of these, further reducing the number available for device interrupts. +In practice this is not an issue because the interrupts are distributed across +many CPUs, so each CPU only receives a small number of vectors. + +During system suspend, however, all secondary CPUs are taken offline and all +interrupts are migrated to the single CPU that remains online. This can exhaust +the available interrupt vectors on that CPU and cause the suspend operation to +fail. + +Affinity‑managed interrupts address this limitation. Each interrupt is assigned +a CPU affinity mask that specifies the set of CPUs on which the interrupt may +be targeted. When a CPU in the mask goes offline, the interrupt is moved to the +next CPU in the mask. If the last CPU in the mask goes offline, the interrupt +is shut down. Drivers using affinity‑managed interrupts must ensure that the +associated queue is quiesced before the interrupt is disabled so that no +further interrupts are generated. When a CPU in the affinity mask comes back +online, the interrupt is re‑enabled. + +Implementation +-------------- + +Devices must provide per‑instance interrupts, such as per‑I/O‑queue interrupts +for storage devices like NVMe. The driver allocates interrupt vectors with the +required affinity settings using struct irq_affinity. For MSI‑X devices, this +is done via pci_alloc_irq_vectors_affinity() with the PCI_IRQ_AFFINITY flag +set. + +Based on the provided affinity information, the IRQ core attempts to spread the +interrupts evenly across the system. The affinity masks are computed during +this allocation step, but the final IRQ assignment is performed when +request_irq() is invoked. + +Isolated CPUs +------------- + +The affinity of managed interrupts is handled entirely in the kernel and cannot +be modified from user space through the /proc interfaces. The managed_irq +sub‑parameter of the isolcpus boot option specifies a CPU mask that managed +interrupts should attempt to avoid. This isolation is best‑effort and only +applies if the automatically assigned interrupt mask also contains online CPUs +outside the avoided mask. If the requested mask contains only isolated CPUs, +the setting has no effect. + +CPUs listed in the avoided mask remain part of the interrupt’s affinity mask. +This means that if all non‑isolated CPUs go offline while isolated CPUs remain +online, the interrupt will be assigned to one of the isolated CPUs. + +The following examples assume a system with 8 CPUs. + +- A QEMU instance is booted with "-device virtio-scsi-pci". + The MSI‑X device exposes 11 interrupts: 3 "management" interrupts and 8 + "queue" interrupts. The driver requests the 8 queue interrupts, each of which + is affine to exactly one CPU. If that CPU goes offline, the interrupt is shut + down. + + Assuming interrupt 48 is one of the queue interrupts, the following appears:: + + /proc/irq/48/effective_affinity_list:7 + /proc/irq/48/smp_affinity_list:7 + + This indicates that the interrupt is served only by CPU7. Shutting down CPU7 + does not migrate the interrupt to another CPU:: + + /proc/irq/48/effective_affinity_list:0 + /proc/irq/48/smp_affinity_list:7 + + This can be verified via the debugfs interface + (/sys/kernel/debug/irq/irqs/48). The dstate field will include + IRQD_IRQ_DISABLED, IRQD_IRQ_MASKED and IRQD_MANAGED_SHUTDOWN. + +- A QEMU instance is booted with "-device virtio-scsi-pci,num_queues=2" + and the kernel command line includes: + "irqaffinity=0,1 isolcpus=domain,2-7 isolcpus=managed_irq,1-3,5-7". + The MSI‑X device exposes 5 interrupts: 3 management interrupts and 2 queue + interrupts. The management interrupts follow the irqaffinity= setting. The + queue interrupts are spread across available CPUs:: + + /proc/irq/47/effective_affinity_list:0 + /proc/irq/47/smp_affinity_list:0-3 + /proc/irq/48/effective_affinity_list:4 + /proc/irq/48/smp_affinity_list:4-7 + + The two queue interrupts are evenly distributed. Interrupt 48 is placed on CPU4 + because the managed_irq mask avoids CPUs 5–7 when possible. + + Replacing the managed_irq argument with "isolcpus=managed_irq,1-3,4-5,7" + results in:: + + /proc/irq/48/effective_affinity_list:6 + /proc/irq/48/smp_affinity_list:4-7 + + Interrupt 48 is now served on CPU6 because the system avoids CPUs 4, 5 and + 7. If CPU6 is taken offline, the interrupt migrates to one of the "isolated" + CPUs:: + + /proc/irq/48/effective_affinity_list:7 + /proc/irq/48/smp_affinity_list:4-7 + + The interrupt is shut down once all CPUs listed in its smp_affinity mask are + offline. From f0efd29aa60cb3399c79c0a041d1f1c0a4367862 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 2 Apr 2026 11:47:49 +0200 Subject: [PATCH 161/162] doc: Add CPU Isolation documentation nohz_full was introduced in v3.10 in 2013, which means this documentation is overdue for 13 years. Fortunately Paul wrote a part of the needed documentation a while ago, especially concerning nohz_full in Documentation/timers/no_hz.rst and also about per-CPU kthreads in Documentation/admin-guide/kernel-per-CPU-kthreads.rst Introduce a new page that gives an overview of CPU isolation in general. Acked-by: Waiman Long Reviewed-by: Valentin Schneider Reviewed-by: Sebastian Andrzej Siewior Signed-off-by: Frederic Weisbecker Reviewed-by: Paul E. McKenney Signed-off-by: Jonathan Corbet Message-ID: <20260402094749.18879-1-frederic@kernel.org> --- Documentation/admin-guide/cpu-isolation.rst | 357 ++++++++++++++++++++ Documentation/admin-guide/index.rst | 1 + 2 files changed, 358 insertions(+) create mode 100644 Documentation/admin-guide/cpu-isolation.rst diff --git a/Documentation/admin-guide/cpu-isolation.rst b/Documentation/admin-guide/cpu-isolation.rst new file mode 100644 index 000000000000..8c65d03fd28c --- /dev/null +++ b/Documentation/admin-guide/cpu-isolation.rst @@ -0,0 +1,357 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +CPU Isolation +============= + +Introduction +============ + +"CPU Isolation" means leaving a CPU exclusive to a given workload +without any undesired code interference from the kernel. + +Those interferences, commonly pointed out as "noise", can be triggered +by asynchronous events (interrupts, timers, scheduler preemption by +workqueues and kthreads, ...) or synchronous events (syscalls and page +faults). + +Such noise usually goes unnoticed. After all, synchronous events are a +component of the requested kernel service. And asynchronous events are +either sufficiently well-distributed by the scheduler when executed +as tasks or reasonably fast when executed as interrupt. The timer +interrupt can even execute 1024 times per seconds without a significant +and measurable impact most of the time. + +However some rare and extreme workloads can be quite sensitive to +those kinds of noise. This is the case, for example, with high +bandwidth network processing that can't afford losing a single packet +or very low latency network processing. Typically those use cases +involve DPDK, bypassing the kernel networking stack and performing +direct access to the networking device from userspace. + +In order to run a CPU without or with limited kernel noise, the +related housekeeping work needs to be either shut down, migrated or +offloaded. + +Housekeeping +============ + +In the CPU isolation terminology, housekeeping is the work, often +asynchronous, that the kernel needs to process in order to maintain +all its services. It matches the noises and disturbances enumerated +above except when at least one CPU is isolated. Then housekeeping may +make use of further coping mechanisms if CPU-tied work must be +offloaded. + +Housekeeping CPUs are the non-isolated CPUs where the kernel noise +is moved away from isolated CPUs. + +The isolation can be implemented in several ways depending on the +nature of the noise: + +- Unbound work, where "unbound" means not tied to any CPU, can be + simply migrated away from isolated CPUs to housekeeping CPUs. + This is the case of unbound workqueues, kthreads and timers. + +- Bound work, where "bound" means tied to a specific CPU, usually + can't be moved away as-is by nature. Either: + + - The work must switch to a locked implementation. E.g.: + This is the case of RCU with CONFIG_RCU_NOCB_CPU. + + - The related feature must be shut down and considered + incompatible with isolated CPUs. E.g.: Lockup watchdog, + unreliable clocksources, etc... + + - An elaborate and heavyweight coping mechanism stands as a + replacement. E.g.: the timer tick is shut down on nohz_full + CPUs but with the constraint of running a single task on + them. A significant cost penalty is added on kernel entry/exit + and a residual 1Hz scheduler tick is offloaded to housekeeping + CPUs. + +In any case, housekeeping work has to be handled, which is why there +must be at least one housekeeping CPU in the system, preferably more +if the machine runs a lot of CPUs. For example one per node on NUMA +systems. + +Also CPU isolation often means a tradeoff between noise-free isolated +CPUs and added overhead on housekeeping CPUs, sometimes even on +isolated CPUs entering the kernel. + +Isolation features +================== + +Different levels of isolation can be configured in the kernel, each of +which has its own drawbacks and tradeoffs. + +Scheduler domain isolation +-------------------------- + +This feature isolates a CPU from the scheduler topology. As a result, +the target isn't part of the load balancing. Tasks won't migrate +either from or to it unless affined explicitly. + +As a side effect the CPU is also isolated from unbound workqueues and +unbound kthreads. + +Requirements +~~~~~~~~~~~~ + +- CONFIG_CPUSETS=y for the cpusets-based interface + +Tradeoffs +~~~~~~~~~ + +By nature, the system load is overall less distributed since some CPUs +are extracted from the global load balancing. + +Interfaces +~~~~~~~~~~ + +- Documentation/admin-guide/cgroup-v2.rst cpuset isolated partitions are recommended + because they are tunable at runtime. + +- The 'isolcpus=' kernel boot parameter with the 'domain' flag is a + less flexible alternative that doesn't allow for runtime + reconfiguration. + +IRQs isolation +-------------- + +Isolate the IRQs whenever possible, so that they don't fire on the +target CPUs. + +Interfaces +~~~~~~~~~~ + +- The file /proc/irq/\*/smp_affinity as explained in detail in + Documentation/core-api/irq/irq-affinity.rst page. + +- The "irqaffinity=" kernel boot parameter for a default setting. + +- The "managed_irq" flag in the "isolcpus=" kernel boot parameter + tries a best effort affinity override for managed IRQs. + +Full Dynticks (aka nohz_full) +----------------------------- + +Full dynticks extends the dynticks idle mode, which stops the tick when +the CPU is idle, to CPUs running a single task in userspace. That is, +the timer tick is stopped if the environment allows it. + +Global timer callbacks are also isolated from the nohz_full CPUs. + +Requirements +~~~~~~~~~~~~ + +- CONFIG_NO_HZ_FULL=y + +Constraints +~~~~~~~~~~~ + +- The isolated CPUs must run a single task only. Multitask requires + the tick to maintain preemption. This is usually fine since the + workload usually can't stand the latency of random context switches. + +- No call to the kernel from isolated CPUs, at the risk of triggering + random noise. + +- No use of POSIX CPU timers on isolated CPUs. + +- Architecture must have a stable and reliable clocksource (no + unreliable TSC that requires the watchdog). + + +Tradeoffs +~~~~~~~~~ + +In terms of cost, this is the most invasive isolation feature. It is +assumed to be used when the workload spends most of its time in +userspace and doesn't rely on the kernel except for preparatory +work because: + +- RCU adds more overhead due to the locked, offloaded and threaded + callbacks processing (the same that would be obtained with "rcu_nocbs" + boot parameter). + +- Kernel entry/exit through syscalls, exceptions and IRQs are more + costly due to fully ordered RmW operations that maintain userspace + as RCU extended quiescent state. Also the CPU time is accounted on + kernel boundaries instead of periodically from the tick. + +- Housekeeping CPUs must run a 1Hz residual remote scheduler tick + on behalf of the isolated CPUs. + +Checklist +========= + +You have set up each of the above isolation features but you still +observe jitters that trash your workload? Make sure to check a few +elements before proceeding. + +Some of these checklist items are similar to those of real-time +workloads: + +- Use mlock() to prevent your pages from being swapped away. Page + faults are usually not compatible with jitter sensitive workloads. + +- Avoid SMT to prevent your hardware thread from being "preempted" + by another one. + +- CPU frequency changes may induce subtle sorts of jitter in a + workload. Cpufreq should be used and tuned with caution. + +- Deep C-states may result in latency issues upon wake-up. If this + happens to be a problem, C-states can be limited via kernel boot + parameters such as processor.max_cstate or intel_idle.max_cstate. + More finegrained tunings are described in + Documentation/admin-guide/pm/cpuidle.rst page + +- Your system may be subject to firmware-originating interrupts - x86 has + System Management Interrupts (SMIs) for example. Check your system BIOS + to disable such interference, and with some luck your vendor will have + a BIOS tuning guidance for low-latency operations. + + +Full isolation example +====================== + +In this example, the system has 8 CPUs and the 8th is to be fully +isolated. Since CPUs start from 0, the 8th CPU is CPU 7. + +Kernel parameters +----------------- + +Set the following kernel boot parameters to disable SMT and setup tick +and IRQ isolation: + +- Full dynticks: nohz_full=7 + +- IRQs isolation: irqaffinity=0-6 + +- Managed IRQs isolation: isolcpus=managed_irq,7 + +- Prevent SMT: nosmt + +The full command line is then: + + nohz_full=7 irqaffinity=0-6 isolcpus=managed_irq,7 nosmt + +CPUSET configuration (cgroup v2) +-------------------------------- + +Assuming cgroup v2 is mounted to /sys/fs/cgroup, the following script +isolates CPU 7 from scheduler domains. + +:: + + cd /sys/fs/cgroup + # Activate the cpuset subsystem + echo +cpuset > cgroup.subtree_control + # Create partition to be isolated + mkdir test + cd test + echo +cpuset > cgroup.subtree_control + # Isolate CPU 7 + echo 7 > cpuset.cpus + echo "isolated" > cpuset.cpus.partition + +The userspace workload +---------------------- + +Fake a pure userspace workload, the program below runs a dummy +userspace loop on the isolated CPU 7. + +:: + + #include + #include + #include + #include + int main(void) + { + // Move the current task to the isolated cpuset (bind to CPU 7) + int fd = open("/sys/fs/cgroup/test/cgroup.procs", O_WRONLY); + if (fd < 0) { + perror("Can't open cpuset file...\n"); + return 0; + } + + write(fd, "0\n", 2); + close(fd); + + // Run an endless dummy loop until the launcher kills us + while (1) + ; + + return 0; + } + +Build it and save for later step: + +:: + + # gcc user_loop.c -o user_loop + +The launcher +------------ + +The below launcher runs the above program for 10 seconds and traces +the noise resulting from preempting tasks and IRQs. + +:: + + TRACING=/sys/kernel/tracing/ + # Make sure tracing is off for now + echo 0 > $TRACING/tracing_on + # Flush previous traces + echo > $TRACING/trace + # Record disturbance from other tasks + echo 1 > $TRACING/events/sched/sched_switch/enable + # Record disturbance from interrupts + echo 1 > $TRACING/events/irq_vectors/enable + # Now we can start tracing + echo 1 > $TRACING/tracing_on + # Run the dummy user_loop for 10 seconds on CPU 7 + ./user_loop & + USER_LOOP_PID=$! + sleep 10 + kill $USER_LOOP_PID + # Disable tracing and save traces from CPU 7 in a file + echo 0 > $TRACING/tracing_on + cat $TRACING/per_cpu/cpu7/trace > trace.7 + +If no specific problem arose, the output of trace.7 should look like +the following: + +:: + + -0 [007] d..2. 1980.976624: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=user_loop next_pid=1553 next_prio=120 + user_loop-1553 [007] d.h.. 1990.946593: reschedule_entry: vector=253 + user_loop-1553 [007] d.h.. 1990.946593: reschedule_exit: vector=253 + +That is, no specific noise triggered between the first trace and the +second during 10 seconds when user_loop was running. + +Debugging +========= + +Of course things are never so easy, especially on this matter. +Chances are that actual noise will be observed in the aforementioned +trace.7 file. + +The best way to investigate further is to enable finer grained +tracepoints such as those of subsystems producing asynchronous +events: workqueue, timer, irq_vector, etc... It also can be +interesting to enable the tick_stop event to diagnose why the tick is +retained when that happens. + +Some tools may also be useful for higher level analysis: + +- Documentation/tools/rtla/rtla.rst provides a suite of tools to analyze + latency and noise in the system. For example Documentation/tools/rtla/rtla-osnoise.rst + runs a kernel tracer that analyzes and output a summary of the noises. + +- dynticks-testing does something similar to rtla-osnoise but in userspace. It is available + at git://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst index b734f8a2a2c4..cd28dfe91b06 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -94,6 +94,7 @@ likely to be of interest on almost any system. cgroup-v2 cgroup-v1/index + cpu-isolation cpu-load mm/index module-signing From 40a3f6c5e2604ff7c007da6628120529569e950c Mon Sep 17 00:00:00 2001 From: Sukrut Heroorkar Date: Sat, 11 Apr 2026 17:51:19 +0200 Subject: [PATCH 162/162] Documentation: core-api: real-time: correct spelling Fix typo "excpetion" with "exception". Signed-off-by: Sukrut Heroorkar Signed-off-by: Jonathan Corbet Message-ID: <20260411155120.233357-1-hsukrut3@gmail.com> --- Documentation/core-api/real-time/architecture-porting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/core-api/real-time/architecture-porting.rst b/Documentation/core-api/real-time/architecture-porting.rst index c90a426d8062..c9a39d708866 100644 --- a/Documentation/core-api/real-time/architecture-porting.rst +++ b/Documentation/core-api/real-time/architecture-porting.rst @@ -74,7 +74,7 @@ Exception handlers Enabling interrupts is especially important on PREEMPT_RT, where certain locks, such as spinlock_t, become sleepable. For example, handling an invalid opcode may result in sending a SIGILL signal to the user task. A - debug excpetion will send a SIGTRAP signal. + debug exception will send a SIGTRAP signal. In both cases, if the exception occurred in user space, it is safe to enable interrupts early. Sending a signal requires both interrupts and kernel preemption to be enabled.