MAC0470 - Desenvolvimento de Software Livre

Tutorial 1: Setting up a test environment for Linux Kernel Dev using QEMU and libvirt

Neste primeiro tutorial mostra como instalar e configurar uma máquina virtual com QEMU e libvirt, criando um ambiente isolado para compilar e testar modificações no kernel. Para simplificar todas as etapas, é utilizado um script (activate.sh) que automatiza a definição de variáveis de ambiente, caminhos e funções auxiliares. Além disso, configuramos o SSH no guest, permitindo acesso remoto e transferência de arquivos de maneira rápida e segura entre a VM e o sistema hospedeiro.


Tutorial 3: Introduction to Linux kernel build configuration and modules

Nesse tutorial ensina como criar, compilar e executar um módulo do kernel Linux na VM. Para isso, foi criado um arquivo .c e feita as configurações no Kconfig e no Makefile, habilitamos a compilação como módulo e fizemos o build. Em seguida, na VM com o kernel modificado, testamos o carregamento e o uso do módulo.


Minha Experiência com os Tutoriais

Os problemas que tive com os tutoriais foram bem pontuais como esquecer de definir uma variável, usar a imagem errada, enfrentar dificuldades com permissões ou lidar com a desconfiguração do IP do SSH.


1ª Contribuição para o Kernel do Linux

  • Escolha do Patch e Refatoração

    Eu e minha dupla, Bianca Galvão, trabalhamos em uma contribuição para o subsistema IIO (Industrial I/O). Escolhemos uma das sugestões dos monitores para eliminar uma duplicação de código no driver do sensor MMC35240. O problema envolvia duas funções com lógica quase idêntica — mmc35240_is_writeable_reg, que determina que apenas os registradores CTRL0 e CTRL1 são graváveis, e mmc35240_is_volatile_reg, que indica que todos os registradores, exceto CTRL0 e CTRL1, são voláteis — mas com resultados opostos para os mesmos casos de teste.

    Para resolver isso, criamos uma função auxiliar que verifica se o registrador é CTRL0 ou CTRL1 e, a partir dela, simplificamos ambas as funções originais, invertendo o retorno quando necessário. Todas as mudanças foram feitas em uma branch, seguindo as boas práticas.

  • Teste de Validação da Contribuição

    Como não sabíamos como testar diretamente a função, validamos a contribuição apenas pela compilação do módulo: habilitamos o driver normalmente, inserimos uma linha de código que certamente quebraria o build (realmente quebrou), removemos essa linha e, ao compilar novamente, tudo foi gerado sem erros.

  • Commit

    Após refatorar, testar e compilar, fizemos o commit seguindo o esqueleto padrão — identificamos o subsistema e o diretório, o assunto e descrevemos detalhadamente as modificações. Em seguida, para validar o estilo de código executamos:

    git format-patch -1 --stdout | ./scripts/checkpatch.pl
    

    O script apontou alguns avisos pertinentes, que foram corrigidos.

  • Envio do Patch

    Na etapa de envio do patch, a configuração do email foi tranquila: usamos o kw, que oferece um formato mais interativo e prático. A maior complicação surgiu ao tentar usar o email da USP — não conseguimos completar a autenticação — então migramos para o Gmail pessoal, o que simplificou o processo e funcionou.

  • Contribuição
    +static bool mmc35240_reg_check(unsigned int reg)
    +{
    +       return reg == MMC35240_REG_CTRL0 || reg == MMC35240_REG_CTRL1;
    +}
    +
    static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg)
    {
    
    -       switch (reg) {
    -       case MMC35240_REG_CTRL0:
    -       case MMC35240_REG_CTRL1:
    -               return true;
    -       default:
    -               return false;
    -       }
    
    +       return mmc35240_reg_check(reg);
    
    }
    
    
    static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg)
    {
    
    -       switch (reg) {
    -       case MMC35240_REG_CTRL0:
    -       case MMC35240_REG_CTRL1:
    -               return false;
    -       default:
    -               return true;
    -       }
    
    +       return !mmc35240_reg_check(reg);
    
    }
    
    
  • Feedback

    Recebemos o feedback do Jonathan Cameron. Ele sugeriu que retirássemos a função auxiliar e mantivéssemos a estrutura lógica original da função mmc35240_is_writeable_reg, fazendo com que a função mmc35240_is_volatile_reg simplesmente retornasse o valor inverso de mmc35240_is_writeable_reg, uma vez que isso contribuiria para a clareza e documentação do código. Realizamos as alterações, no entanto, recebemos um novo feedback do Marcelo Schimitt, e infelizmente fomos pegas no tal limite de colunas permitido em um commit. Além disso, por algum motivo, nossa versão 2 não entrou na mesma thread do email inicial, e acabou faltando a explicação da transição da versão 1 para a versão 2. Ainda sobre o feedback, ele comentou que, caso mantivéssemos a abordagem sugerida pelo Jonathan, seria bom explicar por que os registradores voláteis são justamente aqueles que não são graváveis.

    -static bool mmc35240_reg_check(unsigned int reg)
    -{
    -       return reg == MMC35240_REG_CTRL0 || reg == MMC35240_REG_CTRL1;
    -}
    static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg)
    {
    -       return mmc35240_reg_check(reg);
    +       switch (reg) {
    +               case MMC35240_REG_CTRL0:
    +               case MMC35240_REG_CTRL1:
    +                       return true;
    +               default:
    +               return false;
    +       }
    }
    static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg)
    {
    -       return !mmc35240_reg_check(reg);
    +       return !mmc35240_is_writeable_reg(dev, reg);
    }
    
    Ao enviarmos o patch com a adoção da sugestão do Jonathan, tivemos alguns problemas com o checkpatch. Apesar de ele ter sido executado, por algum motivo não identificou os erros relacionados ao uso de espaços em vez de tabs. Além disso, recebemos um feedback sobre o formato da nossa cover letter. Como enviamos a v2 a partir da v1, houve uma confusão em relação à função mmc35240_reg_check(), que não estava sendo encontrada na branch. Após explicarmos o conteúdo da nossa cover letter e o fato de que a função mmc35240_reg_check() não existe na branch testing, o Marcelo respondeu. No entanto, deu a entender que nossa contribuição para uma v3 seria algo pequeno e que talvez não valesse o esforço. Ele sugeriu que, caso realmente enviássemos a v3, utilizássemos algo mais robusto, como o FIELD_PREP e o FIELD_GET .


Contribuindo com Kworkflow

  • 1ª Contribuição

    Primeiro, começamos configurando o ambiente de contribuição, que é bem mais simples do que o do kernel do Linux. Em seguida, para termos um primeiro contato com os mantenedores, decidimos pegar uma issue relacionada à documentação. O problema era que a mensagem de warning exibida após a criação do ambiente estava um pouco confusa, pois não deixava claro que o ambiente já estava pronto para uso. Fizemos a alteração para um aviso mais claro. Recebemos o feedback do Rodrigo Siqueira, que sugeriu acrescentar uma segunda mensagem direcionada ao usuário, além do warning. Acatamos a sugestão e estamos aguardando o feedback final.

    - warning "You don't have a config file, get it from default paths"
    + say "Environment was created without a kernel .config file. Use kw env --use ${env_name} to switch to the new env."
    + warning "The new env does not have a default .config; you must provide it for a correct kernel compilation. It is recommended to use kw kernel-config-manager."
    
  • 2ª Contribuição

    Para nossa segunda contribuição para o KW, decidimos continuar no escopo de refatoração. Nesta em específico, a tarefa consistia em mover variáveis de configuração que estavam no script de deploy para um arquivo próprio de configuração, que o script então passaria a utilizar. O objetivo dessa mudança era facilitar a alteração dos valores definidos pelo usuário, sem que fosse necessário modificar diretamente o script do KW. Para isso, movemos as variáveis para o arquivo deploy.config e começamos a adaptar o arquivo de teste deploy_test.sh para lidar com essa atualização. Foi aí que encontramos uma leve dificuldade: o teste não passava porque não reconhecia as variáveis que havíamos movido. Descobrimos que um dos motivos era o fato de o teste possuir seu próprio arquivo de configuração. Quando identificamos isso, adicionamos as variáveis ali também. No entanto, percebemos que era necessário declará-las explicitamente no arquivo de teste para que fossem carregadas corretamente a partir do novo arquivo. Essa parte acabou sendo resolvida por tentativa e erro, pois algumas variáveis já estavam sendo definidas em outro lugar, e só adicionamos aquelas que realmente estavam sem valor. No geral, foi uma issue que nos permitiu explorar melhor o KW, entender como os arquivos se conectam, como as variáveis são definidas e como se trabalha com arquivos em bash. Além disso, foi uma ótima oportunidade para aprender mais sobre como editar e juntar commits. Inicialmente, fiz o pull request em dois commits, e, ao corrigir algumas coisas, precisei aplicar as alterações mantendo essa divisão, o que foi um pouco trabalhoso por ser minha primeira vez lidando com isso. Logo depois, recebemos o feedback de que seria melhor juntar todas as modificações em um único commit — e lá fui eu descobrir como fazer isso também, o que acabou sendo mais fácil.

  • 3ª Contribuição

    Para finalizar, decidimos fazer uma última contribuição, também focada em refatoração. Dessa vez, a tarefa era mover uma função responsável por configurar a chave SSH dos usuários e do root — que antes estava no arquivo de deploy — para o arquivo remote.sh, que lida com as questões de acesso remoto. A função foi movida sem maiores dificuldades, mas também foi necessário atualizar os testes: removemos o teste correspondente do deploy_test.sh e o transferimos para o remote_test.sh. Durante essa mudança, também precisávamos identificar quais variáveis precisavam ser definidas, mas essa parte foi menos trabalhosa do que na segunda contribuição.


  • Pacotes Debian

    Não tive muitos problemas para configurar o ambiente. Foi uma tarefa que me permitiu, de fato, aprender a criar e utilizar uma VM. A contribuição em si foi simples, principalmente porque já havia uma curadoria prévia dos pacotes. Acredito que, pelo que foi apresentado e explicado sobre o fluxo de manutenção de um pacote, não seja algo absurdamente difícil. As issues parecem bem organizadas, a documentação é boa e a comunidade aparenta ser bastante acessível — especialmente pelo simples fato de dois dos mantenedores terem se disposto a passar duas tardes em contato conosco.