Maintainers and Trees
Get this wrong and nothing else matters. A perfect patch sent to the wrong list, based on the wrong tree, arrives nowhere and gets no reply — and the absence of a reply looks exactly like being ignored, so people conclude the community is unwelcoming when what actually happened is that nobody who could apply it ever saw it.
This chapter answers two questions: who do I send this to, and what do I base it on.
MAINTAINERS Is a Database
It is not documentation. It is a machine-readable index that tooling parses, and it lives at the top of the tree.
cd ~/kernel/linux
wc -l MAINTAINERS
head -80 MAINTAINERS # the field-letter legend is at the top. Read it once.
tail -12 MAINTAINERS # "THE REST" — Linus, the catch-all
The field letters
| Letter | Means | What you do with it |
|---|---|---|
M: | Maintainer | Put on To: |
R: | Designated reviewer | Put on Cc: |
L: | Mailing list | Put on Cc:, always |
S: | Status | Read it before you invest — see below |
T: | Tree | This is what you base your patch on |
F: | Files covered (globs) | How the entry was matched |
X: | Files excluded | An exception carved out of an F: |
N: | Files matched by regex | Catches names F: globs miss |
K: | Keyword regex matched against patch content | Matches you even when no file matches |
P: | Profile document | Read this before your first patch there |
Q: | Patchwork queue | Where your patch will show up as a tracked item |
B: | Bug tracker | Where to report, not where to patch |
C: | Chat (IRC/Matrix) | Useful for "is anyone working on this?" |
W: | Web page | Occasionally has a real developer guide |
What S: actually tells you
| Status | Means | What it implies for you |
|---|---|---|
Supported | Someone is paid to maintain it | Fast, thorough review. High standards. |
Maintained | Someone maintains it, unpaid | Usually responsive; be patient |
Odd Fixes | Minimal maintenance | Trivial fixes accepted; features unlikely |
Orphan | No maintainer | Send to the list and linux-kernel. If you care, you may end up being the maintainer — and volunteering is a legitimate contribution. |
Obsolete | Replaced by something else | Do not spend time here |
Warning:
S:is a self-report and it goes stale. An entry can sayMaintainedwhile the maintainer has not sent a patch in three years. Always cross-check withgit log— the command is in the next section, and it takes five seconds.
get_maintainer.pl
./scripts/get_maintainer.pl -f drivers/gpu/drm/vkms/vkms_drv.c
Rodrigo Siqueira <...> (maintainer:DRM DRIVER FOR VIRTUAL KERNEL MODESETTING)
Melissa Wen <...> (maintainer:DRM DRIVER FOR VIRTUAL KERNEL MODESETTING)
Maíra Canal <...> (reviewer:DRM DRIVER FOR VIRTUAL KERNEL MODESETTING)
dri-devel@lists.freedesktop.org (open list:DRM DRIVERS)
linux-kernel@vger.kernel.org (open list)
The parenthetical says why each name was produced. That matters, because by default the script
also mines git log for people who recently touched the file, and those are suggestions, not
obligations.
| Invocation | Gives you |
|---|---|
-f <file> | Who covers this path |
<patchfile.patch> | Who covers everything the patch touches — use this form on your actual patch |
--scm | Also print the T: tree lines |
--status | Also print the S: status |
--nogit --nogit-fallback | Only MAINTAINERS entries, no git-history guesses |
--norolestats | Drop the parentheticals (for piping into --to/--cc) |
-l / --list-only | Just the lists |
The two you will actually use:
# While exploring: who owns this, and is it alive?
./scripts/get_maintainer.pl --scm --status -f mm/page_alloc.c
# When sending: exactly who goes on this patch.
./scripts/get_maintainer.pl 0001-my-fix.patch
Tip:
git send-emailcan call it for you, which removes a whole class of mistake:git config sendemail.tocmd './scripts/get_maintainer.pl --nogit --nogit-fallback --norolestats --nol' git config sendemail.cccmd './scripts/get_maintainer.pl --nogit --nogit-fallback --norolestats --nom'Review what it produces before sending anyway. The script is a good default, not an oracle — it over-includes on git history and under-includes when a change has cross-subsystem implications.
Who is actually active
MAINTAINERS says who is responsible. git log says who is present.
D=drivers/gpu/drm/vkms
# Is anything happening at all?
git log --oneline --since="6 months ago" -- $D | wc -l
# Who is doing it?
git log --since="1 year ago" --format='%aN' -- $D | sort | uniq -c | sort -rn | head -10
# Who is APPLYING it? (the committer, not the author — this is the maintainer in practice)
git log --since="1 year ago" --format='%cN' -- $D | sort | uniq -c | sort -rn | head -5
# What kind of change gets taken here?
git log --oneline --since="6 months ago" -- $D | head -30
That last command is the most useful thing in this chapter. Read thirty recent commit subjects for the area you want to patch. You will learn the subject-line prefix convention, the granularity of a typical change, and whether your idea resembles anything that has been accepted.
Trees
There is no "the Linux repository". There are hundreds, and your patch's journey is a chain of pulls between them.
flowchart BT
YOU["your patch<br/>sent by email"] --> SUB["subsystem tree<br/>e.g. net-next, tip, drm-misc<br/>the T: line in MAINTAINERS"]
SUB --> NEXT["linux-next<br/>daily integration of ~200 trees<br/>never for production"]
SUB --> LINUS["mainline<br/>git.kernel.org/torvalds/linux<br/>pulled during the merge window"]
LINUS --> STABLE["stable / LTS<br/>6.x.y — backports only"]
LINUS --> DISTRO["distro kernels"]
Finding the right one
./scripts/get_maintainer.pl --scm -f net/core/dev.c
# T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
git remote add net-next https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
git fetch net-next
git branch -r | grep net-next # find the branch — names vary
git switch -c my-fix net-next/main
Branch names are not standardized. You will see main, master, for-next, next, for-6.x,
and <subsys>-next. Look at what the remote actually has; do not assume.
The fixes tree vs. the features tree
Many subsystems keep two, and sending to the wrong one is a guaranteed round trip. Networking is the clearest example and it is also strict about saying which:
| Tree | For | Subject prefix |
|---|---|---|
net | Fixes for the current release | [PATCH net] ... |
net-next | New features, for the next release | [PATCH net-next] ... |
$EDITOR Documentation/process/maintainer-netdev.rst
Other subsystems use for-next versus fixes branches with the same logic. The rule is general:
a bug fix goes to the fixes branch; a feature goes to the next branch, and if you cannot tell
which yours is, that is a question worth asking on the list before writing it.
linux-next
git remote add linux-next https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
git fetch linux-next --tags
git tag -l 'next-*' | tail -5 # a tag per day
Use it to check — "has my area changed under me?", "does my patch conflict with something else in flight?" — and never as a base. Its history is rebuilt daily; a patch against it applies nowhere.
# Is anyone already doing what I am about to do?
git log --oneline linux-next/master --since="1 month ago" -- <the file I want to change>
Where in the Cycle Are You?
The answer changes who reads your patch and how quickly.
git fetch origin --tags
git describe --tags origin/master # e.g. v6.x-rc4-812-gabc1234
git log --oneline --tags --simplify-by-decoration -8 origin/master
git describe says | You are in | Send |
|---|---|---|
v6.X-<n>-g... (no -rc) | The merge window — the two weeks after a release | Nothing new. Maintainers are pulling. Expect silence. |
v6.X-rc1 … -rc4 | Early stabilization | The best time. Features and fixes both get read. |
-rc5 and later | Late stabilization | Fixes only. A feature sent now waits for the next cycle regardless of quality. |
| Any time | A regression in this cycle | Immediately, with Fixes:. This is the highest-priority work there is. |
The arithmetic that follows is in the release cycle: a feature sent at -rc3 appears in a tagged release two to three months later.
Subsystem Profiles
Different subsystems have genuinely different rules, and applying one's norms to another is the most common avoidable mistake after "wrong recipients".
ls Documentation/process/maintainer-*.rst
$EDITOR Documentation/process/maintainer-handbooks.rst
A P: line in a MAINTAINERS entry points at one of these. Read it before your first patch to
that subsystem. Representative differences you will actually hit:
| Subsystem | Something it wants that others do not |
|---|---|
| netdev | The target tree in the subject ([PATCH net] vs [PATCH net-next]); a strict Patchwork queue; net-next closes during the merge window; reverse-Christmas-tree local declarations |
| tip (x86, sched, timers, locking) | Exacting commit-message prose — imperative mood, no "this patch", a clear problem statement; expect to be sent back for wording alone |
| DRM | Group maintainership via drm-misc; committer rights are a thing; dim tooling |
| Device tree bindings | A separate review by different people, on devicetree@vger.kernel.org, with a YAML schema and make dt_binding_check |
| Documentation | Often the fastest to accept a good patch, and a genuinely useful place to start |
| Staging | Deliberately lenient — which is why a staging patch teaches you less about review than any other |
Patchwork and lore
Two pieces of infrastructure you should be able to drive before Lab 7.
lore.kernel.org is every list, archived as a git repository, permalinked by message-ID.
# Read a thread from the command line:
b4 mbox <message-id>
b4 am <message-id> # produce an mbox ready for git am
b4 shazam <message-id> # fetch AND apply the latest version of a series
# Search: https://lore.kernel.org/all/?q=<terms>
Patchwork (patchwork.kernel.org) turns list traffic into a queue with states. If a subsystem
has a Q: line, your patch appears there automatically and its state is how the maintainer tracks
it:
| State | Means |
|---|---|
New | Received, not yet triaged |
Under Review | Someone is looking |
Changes Requested | Your move. Send a v2. |
Accepted | Applied to a tree |
Superseded | A later version replaced it |
Rejected / Not Applicable | Read the thread for why |
Checking your patch's Patchwork state is how you tell "ignored" from "queued", which is exactly the ambiguity that makes people give up.
Reading Exercise
Do this for the subsystem you intend to contribute to. Twenty minutes.
D=<your directory> # e.g. drivers/gpu/drm/vkms
# 1. Who, formally?
./scripts/get_maintainer.pl --scm --status -f $D
# 2. Who, actually?
git log --since="1 year ago" --format='%cN' -- $D | sort | uniq -c | sort -rn | head
# 3. Is it alive?
git log --oneline --since="6 months ago" -- $D | wc -l
# 4. What gets accepted?
git log --oneline --since="6 months ago" -- $D | head -30
# 5. What does a typical commit look like in full?
git log -3 --format='%n=== %h %s%n%n%b' -- $D
# 6. Is there a profile?
grep -A 20 -B 2 "$D" MAINTAINERS | grep -E '^[PQBCTW]:'
# 7. What is in flight right now?
# https://lore.kernel.org/ → search the list name and the file name
Write down the answers. That page is your targeting document for Lab 7, and it takes less time than composing one email badly.
Common Mistakes and Their Symptoms
| Mistake | Symptom | Fix |
|---|---|---|
Only To: the maintainer, no list | The patch is not in the public archive; no review; it cannot be applied by anyone else | Always Cc the L: lines |
Cc'ing linux-kernel@vger only | Nobody who owns the code is subscribed to that firehose | Cc the subsystem list |
Using get_maintainer.pl output uncritically | Twelve people who once touched the file get mail they did not want | Use --nogit --nogit-fallback as the base, then add deliberately |
Basing on master when the subsystem has a tree | "Does not apply to net-next" | --scm, add the remote, base on its branch |
Basing on linux-next | Applies nowhere | Never |
[PATCH net-next] during the merge window | Bounced by policy, not by judgement | Check git describe; read the profile |
| Sending a feature at -rc6 | Silence, then a request to resend next cycle | Send at -rc1..-rc4 |
Assuming S: Maintained means active | Silence | Cross-check with git log --since |
Not reading the P: profile | A rule you broke that everyone else knows | ls Documentation/process/maintainer-*.rst |
| Concluding you are being ignored | You stop contributing | Check Patchwork state and lore first |
Validation / Self-check
- What do
M:,R:,L:,S:,T:,P:, andQ:mean, and which of them go onTo:versusCc:? - What are the five
S:values, and what does each imply about whether to invest your time? - Why is
S: Maintainednot sufficient evidence that a subsystem is active? What command settles it? - What does
get_maintainer.plproduce besidesMAINTAINERSentries, and how do you turn that off? - Which form of
get_maintainer.plshould you run on your actual patch, and why not the-fform? - Name three trees your patch passes through between
git send-emailand a tagged release. - Why must you never base a patch on
linux-next? What is it for instead? - What is the difference between
netandnet-next, and how does a reader of your email know which you targeted? - Where in the release cycle should you send a new feature, and why not during the merge window?
- You want to patch a subsystem you have never touched. List the seven commands from the reading exercise, in order, and say what each one tells you.
- Your patch has had no reply in ten days. Name three places to look before concluding anything.
- A
MAINTAINERSentry has aP:line. What do you do, and what is the risk of skipping it?
Next: Patch Craft — what makes one patch one patch, and what a commit message is actually for.