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

LetterMeansWhat you do with it
M:MaintainerPut on To:
R:Designated reviewerPut on Cc:
L:Mailing listPut on Cc:, always
S:StatusRead it before you invest — see below
T:TreeThis is what you base your patch on
F:Files covered (globs)How the entry was matched
X:Files excludedAn exception carved out of an F:
N:Files matched by regexCatches names F: globs miss
K:Keyword regex matched against patch contentMatches you even when no file matches
P:Profile documentRead this before your first patch there
Q:Patchwork queueWhere your patch will show up as a tracked item
B:Bug trackerWhere to report, not where to patch
C:Chat (IRC/Matrix)Useful for "is anyone working on this?"
W:Web pageOccasionally has a real developer guide

What S: actually tells you

StatusMeansWhat it implies for you
SupportedSomeone is paid to maintain itFast, thorough review. High standards.
MaintainedSomeone maintains it, unpaidUsually responsive; be patient
Odd FixesMinimal maintenanceTrivial fixes accepted; features unlikely
OrphanNo maintainerSend to the list and linux-kernel. If you care, you may end up being the maintainer — and volunteering is a legitimate contribution.
ObsoleteReplaced by something elseDo not spend time here

Warning: S: is a self-report and it goes stale. An entry can say Maintained while the maintainer has not sent a patch in three years. Always cross-check with git 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.

InvocationGives you
-f <file>Who covers this path
<patchfile.patch>Who covers everything the patch touches — use this form on your actual patch
--scmAlso print the T: tree lines
--statusAlso print the S: status
--nogit --nogit-fallbackOnly MAINTAINERS entries, no git-history guesses
--norolestatsDrop the parentheticals (for piping into --to/--cc)
-l / --list-onlyJust 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-email can 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:

TreeForSubject prefix
netFixes for the current release[PATCH net] ...
net-nextNew 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 saysYou are inSend
v6.X-<n>-g... (no -rc)The merge window — the two weeks after a releaseNothing new. Maintainers are pulling. Expect silence.
v6.X-rc1 … -rc4Early stabilizationThe best time. Features and fixes both get read.
-rc5 and laterLate stabilizationFixes only. A feature sent now waits for the next cycle regardless of quality.
Any timeA regression in this cycleImmediately, 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:

SubsystemSomething it wants that others do not
netdevThe 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
DRMGroup maintainership via drm-misc; committer rights are a thing; dim tooling
Device tree bindingsA separate review by different people, on devicetree@vger.kernel.org, with a YAML schema and make dt_binding_check
DocumentationOften the fastest to accept a good patch, and a genuinely useful place to start
StagingDeliberately 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:

StateMeans
NewReceived, not yet triaged
Under ReviewSomeone is looking
Changes RequestedYour move. Send a v2.
AcceptedApplied to a tree
SupersededA later version replaced it
Rejected / Not ApplicableRead 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

MistakeSymptomFix
Only To: the maintainer, no listThe patch is not in the public archive; no review; it cannot be applied by anyone elseAlways Cc the L: lines
Cc'ing linux-kernel@vger onlyNobody who owns the code is subscribed to that firehoseCc the subsystem list
Using get_maintainer.pl output uncriticallyTwelve people who once touched the file get mail they did not wantUse --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-nextApplies nowhereNever
[PATCH net-next] during the merge windowBounced by policy, not by judgementCheck git describe; read the profile
Sending a feature at -rc6Silence, then a request to resend next cycleSend at -rc1..-rc4
Assuming S: Maintained means activeSilenceCross-check with git log --since
Not reading the P: profileA rule you broke that everyone else knowsls Documentation/process/maintainer-*.rst
Concluding you are being ignoredYou stop contributingCheck Patchwork state and lore first

Validation / Self-check

  1. What do M:, R:, L:, S:, T:, P:, and Q: mean, and which of them go on To: versus Cc:?
  2. What are the five S: values, and what does each imply about whether to invest your time?
  3. Why is S: Maintained not sufficient evidence that a subsystem is active? What command settles it?
  4. What does get_maintainer.pl produce besides MAINTAINERS entries, and how do you turn that off?
  5. Which form of get_maintainer.pl should you run on your actual patch, and why not the -f form?
  6. Name three trees your patch passes through between git send-email and a tagged release.
  7. Why must you never base a patch on linux-next? What is it for instead?
  8. What is the difference between net and net-next, and how does a reader of your email know which you targeted?
  9. Where in the release cycle should you send a new feature, and why not during the merge window?
  10. 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.
  11. Your patch has had no reply in ten days. Name three places to look before concluding anything.
  12. A MAINTAINERS entry has a P: 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.