Submetendo um patch para o Kernel do Linux

patch para o Kernel
Este post faz parte da série Kernel Linux. Leia também os outros posts da série:

Introdução

 

Este é o último artigo da série sobre o processo de desenvolvimento do Kernel do Linux. Nos dois artigos anteriores, o processo de desenvolvimento do Kernel foi apresentado, bem como o padrão de codificação utilizado. Este artigo irá apresentar, de forma prática, o processo de submissão de um patch para o Kernel. A priori, este processo é o mesmo adotado em muitos projetos open source. Será mostrado como gerar um patch utilizando o git, a utilização do script get_maintainer.pl que "descobre" os mantedores e lista de e-mail para o qual o patch deve ser destinado, e, por fim, como configurar o git para enviar o patch por e-mail.

 

 

O processo de submissão de um patch para o kernel

 

Ao trabalhar com o código do Kernel fazendo alterações para correção de bugs ou inclusão de novas funcionalidades, cedo ou tarde, a hora de apresentar o seu trabalho para a comunidade chega, e, eventualmente, a inclusão no Kernel Mainline. A comunidade de desenvolvedores do Kernel desenvolveu uma série de convenções e procedimentos que são usados no processo de postar patches. A utilização destes procedimentos como guias vai tornar mais fácil a vida de todos os envolvidos. 

 

 

Quando postar?

 

Existe uma tentação constante em evitar a postagem de patches até que eles estejam realmente prontos. Para patches simples, não existem muitos problemas em submeter rapidamente. No entanto, se o trabalho sendo feito é complexo, existe um série de benefícios em ganhar feedback da comunidade antes do trabalho estar plenamente completo. Desta forma, você deve sempre considerar postar o progresso do trabalho, ou mesmo disponibilizar uma árvore de git para que desenvolvedores interessados possam dar uma olhada em seu trabalho a qualquer instante.

 

Quando postar código que ainda não é considerado pronto para inclusão, é uma boa ideia dizer isso no post por meio do uso da sigla RFC (request for comments) no início do assunto do e-mail. Também mencione algum trabalho que precisa ser feito e problemas conhecidos. Poucas pessoas vão olhar para patches que estão ainda em progresso, mas estas poucas pessoas podem apresentar ideias que podem ajudar a levar o trabalho para a direção correta.

 

 

Antes de postar

 

Existe algumas coisas que precisam ser feitas antes de você considerar submeter patches para a comunidade de desenvolvedores, incluindo:

  • Teste o código o máximo que você puder. Faça uso de ferramentas de debug do Kernel, garantindo que o Kernel vai compilar com uma quantidade razoável de combinações de configurações. Use cross-compilers para compilar para arquiteturas diferentes, etc;
  • Tenha certeza que seu código é compatível com o padrão de codificação do Kernel;
  • Seu código tem implicações de performance? Se sim, você deve rodar ferramentas de benchmark mostrando o impacto (positivo ou negativo) de sua mudança. Um sumário dos resultados deve ser incluso com o patch;
  • Tenha certeza que você tem o direito de postar um código. Se o código foi desenvolvido no âmbito de uma empresa, esta empresa tem o direito sobre o código e deve decidir se este pode ser liberado sob licença GPL.

 

Como regra geral, tomando estas precauções antes de postar códigos quase sempre se paga no longo prazo, evitando retrabalho.

 

 

Preparação do patch do Kernel

 

Patches devem ser preparados para uma versão específica do Kernel. Como uma regra geral, um patch deve ser baseado no Kernel atual mainline encontrado na árvore git do Linus. Quando baseado na mainline, comece com um release (estável ou RC), ao invés de se basear em um ponto arbitrário qualquer (commit aleatório). Se você estiver desenvolvendo contra algum subsistema específico, você deve submeter o patch contra a árvore mais adequada.

 

Somente modificações muito simples devem ser submetidas como um único patch. Casos mais complexos devem ser quebrados como um conjunto de patches (patch set) como uma série de mudanças lógicas. Construir um conjunto de patches é uma arte, e alguns desenvolvedores gastam uma quantia considerável de tempo tentando criar a forma que será mais apreciada pela comunidade. Existem algumas regras do dedão que podem ser aplicadas de forma a guiar este trabalho:

  • A série de patches que você posta não será, quase que certamente, a série de mudanças encontradas no sistema de controle de versão. Ao contrário, as mudanças que você fizer precisam ser consideradas em sua forma final, e então quebradas de maneira que faça sentido. Os desenvolvedores estão interessados em mudanças discretizadas, auto contidas, e não o caminho que você tomou para chegar a estas mudanças;
  • Cada mudança logicamente independente, deve ser formatada como um patch separado. Estas mudanças podem ser pequenas (ex.: "adicionar um campo a esta estrutura") ou grandes (ex.: adicionar um novo driver significante), mas elas devem ser conceitualmente pequenas e conseguir ser explicadas em somente uma linha (commit log). Cada patch deve fazer uma mudança específica que pode ser revisada indepedentemente e verificada se faz o que diz fazer;
  • Como uma forma de reafirmar o guia acima: não misture diferentes tipos de mudanças em um mesmo patch. Se um único patch corrige um bug de segurança crítico, rearranja algumas estruturas e reformata o código, existe uma chance de que a correção não seja notada adequadamente;
  • Cada patch deve possibilitar a criação de um Kernel que compila e roda apropriadamente; se sua série de patches é interrompida no meio, o resultado também deve ser um Kernel que funcione. Aplicação parcial de uma série de patches é um cenário comum que acontece quando a ferramenta "git bisect" é usada para encontrar regressões; se o resultado é um Kernel que não funciona, você dificultará a vida dos desenvolvedores e usuários que estão engajados na nobre tarefa de rastrear problemas;
  • No entanto, não exagere. Certa vez, um desenvolvedor postou uma série de alterações em um único arquivo composto de 500 patches separados - um ato que não o tornou a pessoa mais famosa na lista de discussão do Kernel. Um patch pode ser razoavelmente grande, contanto que este contenha uma única mudança lógica;
  • Pode ser tentador adicionar toda uma nova infraestrutura com uma série de patches, mas deixar esta infraestrutura sem uso até o patch final na série não é bom. Esta tentação deve ser evitada, se possível. Se esta série incluir regressões, a bisseção de patches vai apontar o último patch como responsável, mesmo que o bug esteja em outro lugar. Sempre que possível, um patch que adiciona código novo deve fazer esse código ativo imediatamente.

 

Trabalhar para criar a série de patches perfeita pode ser um processo frustrante que toma um tempo além do que pensado. Entretanto, quando bem feito, é um tempo muito bem gasto.

 

 

Formatação de patches e mensagens de commits (change logs)

 

Então agora você tem uma perfeita série de patches para postar, mas o trabalho não está terminado ainda. Cada patch precisa ser formatado em uma mensagem que comunica de forma rápida e clara com seu propósito para o resto do mundo! Para esse fim, cada patch vai ser composto do seguinte:

  • Uma linha opcional "From" nomeando o autor do patch. Esta linha é somente necessária se você está enviando o patch de alguém que não você mesmo via email, mas nunca machuca adicioná-la quando em dúvida;
  • Uma linha descrevendo o que o patch faz. Esta mensagem deve ser o suficiente para que o leitor entenda o escopo do patch. Esta é a mensagem que irá aparecer como uma mensagem resumida nos "change logs". Esta mensagem é usualmente iniciada com o nome do subsistema a qual ela se destina, seguida pelo propósito do patch. Por exemplo (não precisa nem mencionar que tudo deve ser em inglês né?):

  • Uma linha em branco seguida por uma descrição detalhada do conteúdo do patch. Esta descrição pode ser tão longa quanto requerida. Esta mensagem deve dizer o que o patch faz e por que ela deve ser aplicada ao Kernel;
  • Uma ou mais tags lines, com, no mínimo, uma linha "Signed-off-by:" seguida pelo autor do patch. Esta linha descreve quem assina o patch. Detalhes sobre ela e outras tags serão apresentadas mais adiante.

 

Os itens acima, juntos, formam o change log do patch. Escrever bons change logs é crucial mas frequentemente negligenciado. Vale a pena gastar tempo discutindo esta questão. Quando você for escrever um change log, você deve manter em mente que um grande número de pessoas vai ler suas palavras. Dentre estas pessoas estão mantedores de subsistemas e revisores que precisam decidir se um patch deve ser incluído; distribuidores e outros mantedores tentando decidir se um patch deve ser portado para outros Kernels mais antigos; caçadores de bug imaginando se um patch é responsável por um problema que estão seguindo; usuários que querem saber como o Kernel tem mudado; e mais. Um bom change log possibilita a propagação de informação da informação necessária para todas essas pessoas em uma forma mais direta e concisa possível.

 

Para este fim, a primeira linha (sumário) deve descrever os efeitos e a motivação para a mudança tão bem quanto a restrição de uma linha permite. A descrição detalhada pode então amplificar estes tópicos e prover mais informações detalhadas e necessárias. Se o patch corrige um bug, cite o commit que introduziu o bug, se possível (e inclua o commit ID e o título deste commit). Se o problema está associado com uma mensagem de log ou saída de compilador, inclua esta mensagem para ajudar outros quando estes estiverem procurando pela solução do mesmo problema. Se a mudança tem o objetivo de suportar outras mudanças em outros patches, diga isso. Se a API interna é modificada, detalhe esta mudança e como outros desenvolvedores devem utilizá-la. Em geral, quanto mais você se por no lugar de quem lerá o change log, melhor o change log (e o Kernel como um todo).

 

Não é necessário dizer que, o change log deve ser o texto usado quando for commitar a mudança no sistema de controle de versão.

 

Tags

 

As tags mencionadas acima são usadas para descrever como os vários desenvolvedores foram associados com o desenvolvimento de um patch. Os tags são as últimas linhas inseridas na mensagem de change log e seguem o seguinte formato:

tag: Nome Completo <email> conteúdo opcional.

 

As tags mais comuns são:

  • Signed-off-by: esta tag é mandatória e deve estar em todo e qualquer patch. Ela é um certificado, ou assinatura, que o desenvolvedor tem o direito de submeter o patch para inclusão no Kernel. Patches sem assinatura não serão aceitos no mainline;
  • Acked-by: indica que outro desenvolvedor está de acordo com a mudança (frequentemente um mantedor do código relevante) que o patch é apropriado para inclusão no Kernel;
  • Tested-by: afirma que a pessoa nomeada testou o patch e atesta que este funciona;
  • Reviewed-by: o nome do desenvolvedor que revisou o patch, assegurando que está correto;
  • Reported-by: nomeia o usuário que reportou o problema que é corrigido por este patch. Esta tag é usada para dar crédito às pessoas que testam o código e nos deixam saber quando as coisas não funcionam corretamente;
  • CC: a pessoa nomeada por essa tag recebeu uma cópia do patch e teve a chance de comentá-lo.

 

Seja cuidadoso quando estiver adicionando tags aos patches. Somente CC: é apropriada para adição sem a explícita permissão da pessoa nomeada.

 

Submetendo o patch

 

Antes de você submeter por e-mail seus patches, existem algumas outras coisas que você deve se preocupar:

  • Você tem certeza que seu cliente de email não irá corromper o patch? Patches que têm grandes quantidades de espaço em branco, oriundos principalmente da tabulação, podem ser modificados por certos clientes de e-mail. O cliente web do Gmail por exemplo faz alterações no texto do e-mail, mesmo que a opção plain text esteja selecionada. Nas referências podemos encontrar clientes de e-mail apropriados para esta tarefa;
  • Você tem certeza que seu patch está livre de erros "bobos"? Você deve sempre checar seus patches com ferramentas como a apresentada no artigo anterior, scripts/checkpatch.pl. Você deve sempre manter em mente que você é mais esperto que a ferramenta e assim, deve ponderar a respeito das correções que devem ser feitas.

 

Patches devem ser sempre enviados como texto "puro" (no mime html my friend). Não os envie como anexo de e-mails, pois isso dificulta a vida de revisores em comentar seções do patch em suas respostas ao e-mail. Ao contrário, coloque o patch diretamente na sua mensagem. Mais a frente veremos algumas ferramentas para facilitar nossa vida durante o envio.

 

Quando enviando patches por e-mail, é importante enviar cópias para todos que possam estar interessados nele. Ao contrário de outros projetos, o Kernel encoraja as pessoas a pecar pelo excesso de cópias. Não assuma que pessoas relevantes para o patch irão vê-lo quando você postar na lista de e-mail. Em particular, cópias devem ir para:

  • O mantenedor do subsistema. O arquivo MANTAINERS é o primeiro lugar para olhar para descobrir quem são os mantenedores;
  • Outros desenvolvedores que têm trabalhado na mesma área - especialmente aqueles que podem estar trabalhando em cima dele agora. Usar o git para ver quem mais tem modificado os arquivos é extremamente aconselhável;
  • Se você está respondendo a um bug report, ou requisição de funcionalidade, copie a pessoa que postou originalmente;
  • Mande uma cópia para lista de e-mais relevantes, ou, se não sobrarem opções, para a lista de e-mail do Kernel;
  • Quando você estiver corrigindo um bug, pense se esta correção de bug deve ir para a próxima atualização de Kernel estável. Se este for o caso, [email protected] deve receber uma cópia do patch. Além disso, adicione um tag "Cc: s[email protected]" dentro da mensagem do patch. Isso fará com que o time de Kernel estável receba uma mensagem quando seu patch for para a árvore mainline.

 

Quando selecionando receptores para um patch, é bom ter uma ideia de quem você pensa que vai eventualmente aceitar o patch e fazer o merge. É possível enviar alguns patches diretamente para Linus Torvalds, para que ele faça o merge. No entanto, normalmente as coisas não são feitas deste jeito. Linus é ocupado,  e existem mantenedores que cuidam de partes específicas do Kernel. Usualmente você vai querer que um mantenedor faça o merge do seu patch. Se você não encontrar um mantenedor óbvio, Andrew Morton é frequentemente o alvo de último caso.

 

O formato canônico para uma linha de patch, que é o assunto do e-mail enviado para lista de e-mails, é algo como:

 

Onde "nn" é um número do patch, "mm" é o número total de patches da série, e "subsys" é o nome do subsistema afetado por este patch. "nn/mm" é omitido quando a série é composta por um único patch.

 

Se você tem uma série significante de patches, é aconselhável enviar um e-mail de introdução como parte "zero". Se você usar essa prática, lembre-se que o e-mail de introdução não será incluido no change log. Assim, garanta que os patches tenham a informação completa sobre o change log.

 

Em geral, a segunda e as partes seguintes de um patch de múltiplas partes devem ser enviados como resposta à primeira parte de forma que todas sejam agrupadas juntas. Como veremos à frente, ferramentas como o git tem comando para enviar emails, formatar e aplicar patches de forma adequada.

 

 

Submetendo um patch na prática

 

Nesta seção veremos como submeter um patch na prática. Vamos assumir que você está utilizando a árvore do Kernel "Vanilla", a árvore do Linus Torvalds. A primeira coisa é clonar este repositório:

 

Em seguida, você deve fazer as modificações nos arquivos de forma a corrigir o bug que você encontrou ou adicionar alguma nova funcionalidade. Feito isso, você deve fazer o commit de suas mudanças com o comando git commit seguindo os padrões para mensagens de commit descritas anteriormente. Além disso, se sua mudança for muito complexa, você deve quebrá-la em uma série lógica e linear de commits, também descrito anteriormente. Vou utilizar como exemplo um commit que fiz no Kernel para corrigir o padrão de codificação de um driver de rede wireless. Segue o log do commit: 

 

Os commits das suas mudanças estão no seu repositório local. Entretanto, devemos transformá-los em patches para que possam ser enviados à respectiva lista de discussão, mantenedores e desenvolvedores relevantes. Para isso, o comando git format-patch é utilizado: 

 

No caso, estamos gerando o arquivo de patch do último commit (parâmetro "-1").  Este valor deve ser alterado de acordo com número de últimos commits que você quer gerar patch. Este comando possui um grande número de parâmetros que possibilitam incluir um prefixo no e-mail do patch (parâmetro "--subject-prefix="), alterar o índice de similaridade do algoritmo de diff (parâmetro -M), possibilitando gerar patches menores, mas com o mesmo efeito. Sugiro a você ler o man pages do comando. O patch gerado a partir do comando anterior, arquivo 0001-staging-rtl8723au-Corrections-in-the-coding-style.patch, tem o seguinte conteúdo: 

 

Note como a ferramenta git format-patch facilitou nossa vida, criando o patch no formato requisitado. Tendo o patch (ou conjunto de patches) em mãos, devemos enviá-los por e-mail à lista de discussão, mantenedores e desenvolvedores relevantes. Podemos descobrir isso olhando a documentação do subsistema e observando os commits anteriores deste mesmo arquivo (ou arquivos). Entretanto, existe uma forma muito mais simples e automática de descobrir isso. Existe um script dentro da pasta scripts do Kernel, get_maintainer.pl, que busca essas informações de commits anteriores. Segue o resultado: 

 

O passo seguinte é enviar o patch para os e-mails apontados pelo script get_maintainer.pl. Isso é feito através do comando git send-email. Este comando não está disponível por padrão junto com o git, e deve ser instalado a parte na sua distribuição. No caso do Fedora, ele está no pacote git-email.noarch. A primeira vez que o comando for utilizado, deve-se configurar uma série de parâmetros, dentre eles o nome, e-mail e configurações do servidor de e-mail. Isto é feito alterando-se o arquivo ~/.gitconfig: 

 

Por fim, executa-se o comando: 

 

Note que o comando anterior irá enviar todos os arquivos com extenção .patch para os e-mails indicados pelos parâmetros --to e --cc.

 

Por fim, é só esperar a resposta dos destinatários do patch. Se tudo correr bem, seu patch será integrado à árvore next para testes e seguindo o processo de desenvolvimento do Kernel. Caso não cause regressões, acabará na árvore do Kernel mainline (árvore do Linus Torvalds). Você receberá e-mails dos mantenedores a cada um desses passos.

 

 

Conclusão

 

Esta série de artigos apresentou o processo de desenvolvimento do Kernel, padrão de codificação e processo de submissão de patches. Foi possível observar que existem uma série de práticas e ferramentas envolvidas no processo de desenvolvimento do Kernel, além da programação do código propriamente dita. Este conjunto de ferramentas e práticas são de suma importância para a evolução coordenada do projeto, pois o mesmo é de extrema complexidade, seja pelo número de contribuidores, ou pela quantidade de código integrada. As práticas e ferramentas adotadas no desenvolvimento do Kernel são muito semelhantes a outros projetos open-source, de forma que é de extrema valia conhecê-las.

 

 

Referências

 

[1] https://www.embarcados.com.br/desenvolvimento-Kernel-linux/

[2] https://www.embarcados.com.br/padrao-de-codificacao-Kernel-linux/

[3] http://lxr.free-electrons.com/source/Documentation/development-process/5.Posting

[4] http://lxr.free-electrons.com/source/Documentation/SubmittingPatches

[5] http://git-scm.com/docs/git-format-patch

[6] http://git-scm.com/docs/git-send-email

Outros artigos da série

<< Kernel Linux: Padrão de codificação
Este post faz da série Kernel Linux. Leia também os outros posts da série:
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

2
Deixe um comentário

avatar
 
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
linux10complicaTom Joel Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
linux10complica
Visitante
linux10complica

Muito bom... parabéns.

Tom Joel
Visitante
Tom Joel

Excelente artigo, parabéns!