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
LevelMeaningWhat to do
ERRORAlmost always realFix it
WARNINGUsually realFix it, or be able to say why not
CHECK (--strict only)Style preferencesFix 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 checkpatch fixes 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:

RuleNote
Tabs, 8 wideNot spaces. If you need more than three levels of indentation, that is the actual message.
Line length80 is the guideline; up to 100 tolerated where it genuinely helps. Never split a string literal to fit — grep-ability wins.
BracesOmitted for a single statement — but if any arm of an if/else needs them, all do
No typedef for structsWith the narrow exceptions the document lists
Function naminglower_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 treeLocal 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

ToolFindsRun it
sparse__user/__iomem/__rcu violations, endianness mistakes, bitwise-type misusemake C=1 (recompiled files) or C=2 (all)
smatchFlow-sensitive bugs: unchecked user data, error-path leaks, impossible conditionsmake CHECK=smatch C=1
CoccinelleSemantic patterns across the tree — including "you leaked this on the error path"make coccicheck MODE=report
W=1Extra compiler warnings maintainers care aboutmake W=1
W=2, W=3Progressively noisierOccasionally useful
clangA different warning set entirely; catches things GCC does notmake 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.

BuildFinds
allmodconfigCode your config never compiles; missing EXPORT_SYMBOL; module-only breakage
allyesconfigSymbol collisions, __init section mismatches
randconfig"This only builds when CONFIG_X is set" — run it a few times
A second architectureEndianness, alignment, 32-bit division, per-arch headers
LLVM=1A different warning set
make W=1What 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.

SystemWhat it doesWhat 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 benchmarksA build failure or new warning, with the exact config that produced it — and often a suggested fix
syzbotContinuously fuzzes mainline and -next with syzkallerCrash reports with a reproducer. Reply #syz test: with a tree and a patch to have it verified.
KernelCIBoots real hardware across many boardsBoot regressions
Subsystem CI (netdev, DRM, …)Per-subsystem build/test, wired into PatchworkA 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

MistakeSymptom
checkpatch warnings in a sent patchYou look like you did not try; credibility is the scarce thing
checkpatch -f on a whole old fileHundreds of findings; a patch nobody can review
Blindly obeying checkpatchYou "fixed" something that was correct
A pure-checkpatch patch on code you have not readA bad first impression, and possibly a real breakage
Reformatting surrounding code"Please split this"
Only building your own configA 0-day mail about an architecture you have never used
Never running sparseA __user or endianness bug that works on your machine only
Ignoring a 0-day reportThe one thing that actually looks bad
Treating a robot report as rejectionYou give up on a patch that needed a two-line fix
Not running W=1The maintainer sees warnings you did not

Validation / Self-check

  1. Give the eight steps of the pre-send checklist, and say which one you would drop under time pressure and why.
  2. What are checkpatch's three severity levels, and how does --strict change what you see?
  3. Why run checkpatch -g on commits rather than -f on files?
  4. Give two cases where checkpatch is wrong, and say how you would defend leaving a finding unfixed.
  5. Why is a patch consisting only of checkpatch fixes a bad first contribution?
  6. What does sparse catch that GCC does not? Give two concrete classes.
  7. What is the difference between make C=1 and C=2, and when do you want each?
  8. Why does allmodconfig break code that builds cleanly for you?
  9. Name four automated systems that will examine your patch, and what each is good at.
  10. What is the correct response to a 0-day report, and what does ignoring one signal?
  11. Name four things no robot can check, which is therefore what human review is for.
  12. 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.