After working on the Linux kernel for Nexus and Pixel phones for nearly a year, and messing around with the excellent Eudyptula challenge, I finally wanted to take a crack at submitting patches upstream to the Linux kernel.

This post is woefully inadequate compared to the existing documentation, which should be preferred.

I figure I’d document my workflow, now that I’ve gotten a few patches accepted (and so I can refer to this post rather than my shell history…). Feedback welcome (open an issue or email me).

Step 1: Setting up an email client

I mostly use git send-email for sending patch files. In my ~/.gitconfig I have added:

1 2 3 4 5 6 [sendemail] ; setup for using git send-email; prompts for password smtpuser = myemailaddr@gmail.com smtpserver = smtp.googlemail.com smtpencryption = tls smtpserverport = 587

To send patches through my gmail account. I don’t add my password so that I don’t have to worry about it when I publish my dotfiles. I simply get prompted every time I want to send an email.

I use mutt to respond to threads when I don’t have a patch to send.

Step 2: Make fixes

How do you find a bug to fix? My general approach to finding bugs in open source C/C++ code bases has been using static analysis, a different compiler, and/or more compiler warnings turned on. The kernel also has an instance of bugzilla running as an issue tracker. Work out of a new branch, in case you choose to abandon it later. Rebase your branch before submitting (pull early, pull often).

Step 3: Thoughtful commit messages

I always run git log <file I modified> to see some of the previous commit messages on the file I modified.

1 2 3 4 5 6 7 8 $ git log arch/x86/Makefile commit a5859c6d7b6114fc0e52be40f7b0f5451c4aba93 ... x86/build: convert function graph '-Os' error to warning commit 3f135e57a4f76d24ae8d8a490314331f0ced40c5 ... x86/build: Mostly disable '-maccumulate-outgoing-args'

The first words of commit messages in Linux are usually <subsystem>/<sub-subsystem>: <descriptive comment> .

Let’s commit, git commit <files> -s . We use the -s flag to git commit to add our signoff. Signing your patches is standard and notes your agreement to the Linux Kernel Certificate of Origin.

Step 4: Generate Patch file

git format-patch HEAD~ . You can use git format-patch HEAD~<number of commits to convert to patches> to turn multiple commits into patch files. These patch files will be emailed to the Linux Kernel Mailing List (lkml). They can be applied with git am <patchfile> . I like to back these files up in another directory for future reference, and cause I still make a lot of mistakes with git.

Step 5: checkpatch

You’re going to want to run the kernel’s linter before submitting. It will catch style issues and other potential issues.

1 2 3 4 $ ./scripts/checkpatch.pl 0001-x86-build-don-t-add-maccumulate-outgoing-args-w-o-co.patch total: 0 errors, 0 warnings, 9 lines checked 0001-x86-build-don-t-add-maccumulate-outgoing-args-w-o-co.patch has no obvious style problems and is ready for submission.

If you hit issues here, fix up your changes, update your commit with git commit --amend <files updated> , rerun format-patch, then rerun checkpatch until you’re good to go.

Step 6: email the patch to yourself

This is good to do when you’re starting off. While I use mutt for responding to email, I use git send-email for sending patches. Once you’ve gotten a hang of the workflow, this step is optional, more of a sanity check.

1 2 $ git send-email \ 0001-x86-build-require-only-gcc-use-maccumulate-outgoing-.patch

You don’t need to use command line arguments to cc yourself, assuming you set up git correctly, git send-email should add you to the cc line as the author of the patch. Send the patch just to yourself and make sure everything looks ok.

Step 7: fire off the patch

Linux is huge, and has a trusted set of maintainers for various subsystems. The MAINTAINERS file keeps track of these, but Linux has a tool to help you figure out where to send your patch:

1 2 3 4 5 6 $ ./scripts/get_maintainer.pl 0001-x86-build-don-t-add-maccumulate-outgoing-args-w-o-co.patch Person A <person@a.com> ( maintainer:X86 ARCHITECTURE ( 32-BIT AND 64-BIT )) Person B <person@b.com> ( maintainer:X86 ARCHITECTURE ( 32-BIT AND 64-BIT )) Person C <person@c.com> ( maintainer:X86 ARCHITECTURE ( 32-BIT AND 64-BIT )) x86@kernel.org ( maintainer:X86 ARCHITECTURE ( 32-BIT AND 64-BIT )) linux-kernel@vger.kernel.org ( open list:X86 ARCHITECTURE ( 32-BIT AND 64-BIT ))

With some additional flags, we can feed this output directly into git send-email .

1 2 3 4 $ git send-email \ --cc-cmd = './scripts/get_maintainer.pl --norolestats 0001-my.patch' \ --cc person@a.com \ 0001-my.patch

Make sure to cc yourself when prompted. Otherwise if you don’t subscribe to LKML, then it will be difficult to reply to feedback. It’s also a good idea to cc any other author that has touched this functionality recently.

Step 8: monitor feedback

Patchwork for the LKML is a great tool for tracking the progress of patches. You should register an account there. I highly recommend bookmarking your submitter link. In Patchwork, click any submitter, then Filters (hidden in the top left), change submitter to your name, click apply, then bookmark it. Here’s what mine looks like. Not much today, and mostly trivial patches, but hopefully this post won’t age well in that regard.

Feedback may or may not be swift. I think my first patch I had to ping a couple of times, but eventually got a response.

Step 9: responding to feedback

Update your file, git commit <changed files> --amend to update your latest commit, git format-patch -v2 HEAD~ , edit the patch file to put the changes below the dash below the signed off lines (example), rerun checkpatch, rerun get_maintainer if the files you modified changed since V1. Next, you need to find the messageID to respond to the thread properly.

In gmail, when viewing the message I want to respond to, you can click “Show Original” from the dropdown near the reply button. From there, copy the MessageID from the top (everything in the angle brackets, but not the brackets themselves). Finally, we send the patch:

1 2 3 4 5 $ git send-email \ --cc-cmd = './scripts/get_maintainer.pl --norolestats 0001-my.patch' \ --cc person@a.com \ --in-reply-to 2017datesandletters@somehostname \ 0001-my.patch

We make sure to add anyone who may have commented on the patch from the mailing list to keep them in the loop. Rinse and repeat 2 through 9 as desired until patch is signed off/acked or rejected.

I’ve added this handy shell function to my ~/.zshrc :

1 2 3 4 5 6 7 function kpatch () { patch = $1 shift git send-email \ --cc-cmd = "./scripts/get_maintainer.pl --norolestats $patch" \ $@ $patch }

That I can then invoke like:

1 kpatch 0001-Input-mousedev-fix-implicit-conversion-warning.patch --cc anyone@else.com

where anyone@else.com is anyone I want to add in additon to what get_maintainer sugguests.

Finding out when your patch gets merged is a little tricky; each subsystem maintainer seems to do things differently. My first patch, I didn’t know it went in until a bot at Google notified me. The maintainers for the second and third patches had bots notify me that it got merged into their trees, but when they send Linus a PR and when that gets merged isn’t immediately obvious.

It’s not like Github where everyone involved gets an email that a PR got merged and the UI changes. While there’s pros and cons to having this fairly decentralized process, and while it is kind of is git’s original designed-for use case, I’d be remiss not to mention that I really miss Github. Getting your first patch acknowledged and even merged is intoxicating and makes you want to contribute more; radio silence has the opposite effect.

Happy hacking!