Style and Checks
Everything in this chapter will be run against your patch whether you run it or not. The only question is whether you find out privately, in thirty seconds, or publicly, three days later, in a mail from a robot with a hundred people Cc'd.
Run them first.
The Pre-Send Checklist
Do this from top to bottom before every git send-email. It takes about ten minutes for a small
patch and it is the difference between a clean first impression and a round trip.
cd ~/kernel/linux
# 1. Style, on your commits (not on files you did not touch).
./scripts/checkpatch.pl --strict -g HEAD~1..HEAD
# 2. It builds, for your config.
make O=../build -j"$(nproc)"
# 3. It builds for configs you do not use. This is what the bots do.
make O=../build-all allmodconfig && make O=../build-all -j"$(nproc)"
# 4. It builds with a different compiler.
make O=../build-clang LLVM=1 defconfig && make O=../build-clang LLVM=1 -j"$(nproc)"
# 5. Static analysis on the files you touched.
make O=../build C=2 W=1 <your/files.o>
make O=../build coccicheck MODE=report M=<your/dir>
# 6. Every commit in the series builds.
git rebase --exec 'make -j$(nproc) O=../build' <base>
# 7. It actually works, under the paranoid kernel.
PROFILE=paranoid ~/kernel-labs/scripts/build-kernel.sh
~/kernel-labs/scripts/run-qemu.sh # and run your test
# 8. The formalities.
grep -c '^Signed-off-by:' *.patch # one per patch
grep '^base-commit:' *.patch # from --base=auto
./scripts/get_maintainer.pl *.patch # the recipients
Documentation/process/submit-checklist.rst is the in-tree version of this list, it is maintained,
and it is shorter than this chapter:
$EDITOR ~/kernel/linux/Documentation/process/submit-checklist.rst
checkpatch.pl
./scripts/checkpatch.pl --strict -f drivers/foo/bar.c # a whole file
./scripts/checkpatch.pl --strict *.patch # a produced patch
./scripts/checkpatch.pl --strict -g HEAD~3.. # your commits
./scripts/checkpatch.pl --strict --show-types -f x.c # so you can name a warning
| Level | Meaning | What to do |
|---|---|---|
ERROR | Almost always real | Fix it |
WARNING | Usually real | Fix it, or be able to say why not |
CHECK (--strict only) | Style preferences | Fix in new code; leave existing code alone |
Two rules that matter more than the tool:
Only check what you touched. checkpatch -f on an old file produces hundreds of findings about
code that is not yours. Fixing them turns a one-line patch into an unreviewable mess. Use -g on
your commits.
Do not blindly obey it. checkpatch is a set of heuristics and it is wrong often enough to
matter — it flags legitimate long lines in strings, misidentifies some macros, and has opinions
about comment style that differ from net/'s actual convention. Understand each finding; fix the
real ones; be able to defend the ones you leave.
Warning: A patch whose entire content is
checkpatchfixes to code you have not read is a classic way to get a bad first impression. It creates review load, risks breaking something you do not understand, and reads as chasing a contribution count rather than fixing anything. If you want to fix style, fix it in code you are already changing for a real reason.
Coding Style, in Practice
$EDITOR ~/kernel/linux/Documentation/process/coding-style.rst
Short, opinionated, and worth reading in full once. The parts people get wrong:
| Rule | Note |
|---|---|
| Tabs, 8 wide | Not spaces. If you need more than three levels of indentation, that is the actual message. |
| Line length | 80 is the guideline; up to 100 tolerated where it genuinely helps. Never split a string literal to fit — grep-ability wins. |
| Braces | Omitted for a single statement — but if any arm of an if/else needs them, all do |
No typedef for structs | With the narrow exceptions the document lists |
| Function naming | lower_snake_case, prefixed with the subsystem or driver |
| Comments | /* … */. net/ and drivers/net/ use a different block-comment opening style from the rest of the tree — match the file you are in. |
| Reverse Christmas tree | Local declarations sorted longest-first. Networking only. |
| SPDX on line 1 | // SPDX-License-Identifier: GPL-2.0 in .c, /* … */ in .h |
There is a .clang-format in the tree. Use it on your new code only:
git diff -U0 --cached | ./scripts/clang-format-diff.py -p1 -i
Never reformat surrounding code in a patch that does something else. A style change mixed into a functional change is one of the fastest ways to be asked to split.
The Static Checkers
| Tool | Finds | Run it |
|---|---|---|
| sparse | __user/__iomem/__rcu violations, endianness mistakes, bitwise-type misuse | make C=1 (recompiled files) or C=2 (all) |
| smatch | Flow-sensitive bugs: unchecked user data, error-path leaks, impossible conditions | make CHECK=smatch C=1 |
| Coccinelle | Semantic patterns across the tree — including "you leaked this on the error path" | make coccicheck MODE=report |
W=1 | Extra compiler warnings maintainers care about | make W=1 |
W=2, W=3 | Progressively noisier | Occasionally useful |
| clang | A different warning set entirely; catches things GCC does not | make LLVM=1 |
# sparse only complains about the files being compiled, so touch yours:
touch drivers/foo/bar.c && make O=../build C=1 drivers/foo/
# Coccinelle can also FIX what it finds:
make coccicheck MODE=patch COCCI=scripts/coccinelle/free/kfree.cocci M=drivers/foo/
sparse is the one that earns its keep for driver work: a __user pointer used directly or a
__le32 compared as native are invisible to GCC, compile fine, and are wrong on half the machines in
the world.
Building the Way the Bots Build
Your config is one point in a space of thousands of CONFIG_ symbols. "It builds for me" carries
almost no information.
| Build | Finds |
|---|---|
allmodconfig | Code your config never compiles; missing EXPORT_SYMBOL; module-only breakage |
allyesconfig | Symbol collisions, __init section mismatches |
randconfig | "This only builds when CONFIG_X is set" — run it a few times |
| A second architecture | Endianness, alignment, 32-bit division, per-arch headers |
LLVM=1 | A different warning set |
make W=1 | What maintainers see |
# The two highest-yield, in one go:
make O=../b-all allmodconfig && make O=../b-all -j"$(nproc)" 2>&1 | tee /tmp/all.log
make O=../b-arm ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig \
&& make O=../b-arm ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j"$(nproc)"
grep -E "warning|error" /tmp/all.log | grep -F "$(git diff --name-only HEAD~1 | head -1)"
The Robots
Four systems will look at your patch without being asked. Knowing what each does removes the surprise and, more importantly, tells you what they cannot catch.
| System | What it does | What it mails you |
|---|---|---|
| Intel 0-day / LKP ("kernel test robot") | Builds your patch across many architectures, compilers, and configs; runs sparse, smatch, and Coccinelle; runs some benchmarks | A build failure or new warning, with the exact config that produced it — and often a suggested fix |
| syzbot | Continuously fuzzes mainline and -next with syzkaller | Crash reports with a reproducer. Reply #syz test: with a tree and a patch to have it verified. |
| KernelCI | Boots real hardware across many boards | Boot regressions |
| Subsystem CI (netdev, DRM, …) | Per-subsystem build/test, wired into Patchwork | A pass/fail on your Patchwork entry |
$EDITOR ~/kernel/linux/Documentation/dev-tools/kselftest.rst
$EDITOR ~/kernel/linux/Documentation/dev-tools/syzbot.rst
Note: A 0-day report is not a rejection and not an insult. It is a free, thorough CI run that nobody paid for, and the correct response is a quick "thanks, fixed in v2". The reports are public and everyone gets them; the only thing that looks bad is ignoring one.
What the robots cannot catch, and therefore what human review is for: whether your change is a good idea, whether the locking is right, whether the ABI is extensible, and whether it belongs in this subsystem at all.
Reading Exercise
# 1. Run checkpatch --strict -f on a file in your subsystem you did NOT write.
# How many findings? How many are real? This calibrates how much to trust it.
./scripts/checkpatch.pl --strict --show-types -f <some file> | tail -30
# 2. Find a 0-day report on lore. Search for "kernel test robot" plus your
# subsystem's list name. Read the report and then the author's reply.
# 3. Find a syzbot report with a reproducer, and read the whole thread
# including the fix. Note how much of the analysis the bot did.
# 4. Run make W=1 on one directory and count how many warnings pre-date you.
make O=../build W=1 drivers/<something>/ 2>&1 | grep -c warning
Common Mistakes and Their Symptoms
| Mistake | Symptom |
|---|---|
checkpatch warnings in a sent patch | You look like you did not try; credibility is the scarce thing |
checkpatch -f on a whole old file | Hundreds of findings; a patch nobody can review |
Blindly obeying checkpatch | You "fixed" something that was correct |
A pure-checkpatch patch on code you have not read | A bad first impression, and possibly a real breakage |
| Reformatting surrounding code | "Please split this" |
| Only building your own config | A 0-day mail about an architecture you have never used |
Never running sparse | A __user or endianness bug that works on your machine only |
| Ignoring a 0-day report | The one thing that actually looks bad |
| Treating a robot report as rejection | You give up on a patch that needed a two-line fix |
Not running W=1 | The maintainer sees warnings you did not |
Validation / Self-check
- Give the eight steps of the pre-send checklist, and say which one you would drop under time pressure and why.
- What are
checkpatch's three severity levels, and how does--strictchange what you see? - Why run
checkpatch -gon commits rather than-fon files? - Give two cases where
checkpatchis wrong, and say how you would defend leaving a finding unfixed. - Why is a patch consisting only of
checkpatchfixes a bad first contribution? - What does
sparsecatch that GCC does not? Give two concrete classes. - What is the difference between
make C=1andC=2, and when do you want each? - Why does
allmodconfigbreak code that builds cleanly for you? - Name four automated systems that will examine your patch, and what each is good at.
- What is the correct response to a 0-day report, and what does ignoring one signal?
- Name four things no robot can check, which is therefore what human review is for.
- Which comment style does
net/use, and how would you find that out without being told?
Next: Lab 7 — Your First Patch. Everything above was preparation; this is the one you actually send.