Goal of this stage
We set out to answer three concrete questions about code-duplication changes on the Linux kernel mailing list:
- How many threads deal with duplication?
- Of those patches, how many were accepted or rejected?
- Comparing between maintainers (accept vs reject): is accepting/rejecting subjective?
To answer them we used LKMLWs dataset of mailing-list filtering discussions about code duplication in the IIO subsystem, enriched every thread with its outcome in Patchwork, and then ran a series of analyses.
Throughout the post the unit of analysis is a thread (a discussion: an original
patch/RFC plus all its replies), grouped by the mailing-list _thread_id. A single
.parquet file (iio-regex-classified-status.parquet) carries every original column
plus the two we derived: duplication_classification and accepted.
Step 1: Initial filtering
The starting point was the LKML dataset. From the full set of roughly
16,291 threads we kept only the messages of the linux-iio mailing list whose
subject or body matched a set of duplication-related regular expressions (terms such as
duplicate, duplicated, duplication). This regex pass is intentionally
broad and lexical: it is meant to have high recall, accepting anything that even
mentions duplication, and it knowingly lets through many false positives (for example
“duplicate index”, “duplicate packet”, “duplicate request”, which have nothing to do
with source-code duplication).
The result of this step is iio-regex.parquet: 7,600 messages grouped into
429 threads. Every later step operates on these 429 threads.
Step 2: Filtering with AI (LLM classification)
Because the regex pass is deliberately noisy, we needed a second, semantic filter to
tell real code-duplication discussions apart from the false positives. We used an LLM
(gpt-5-mini) for this.
A key design decision here: we classify one whole thread at a time, not individual emails. For each thread we send the model every message (subject, body, and code) in order, in a single API call, and ask it to return exactly one label for the whole discussion. The resulting label is then written onto every message of that thread. Very large threads are truncated to a safe number of messages per field so the prompt stays within limits.
The model must answer with one of four labels:
- CODE_DUPLICATION: the thread really discusses duplicated source code (clones, copy-paste, repeated logic, or refactoring that removes such duplication).
- REDUNDANCY_REMOVAL: the thread is about removing redundancy that is not code duplication (redundant checks, dead code, repeated calls, general cleanup).
- NOT_CODE_DUPLICATION: a regex false positive (duplicate index/packet/request…).
- INSUFFICIENT_INFORMATION: not enough context to decide.
Running this over the 429 threads gave:
| Label | Threads |
|---|---|
| NOT_CODE_DUPLICATION | 172 |
| REDUNDANCY_REMOVAL | 132 |
| CODE_DUPLICATION | 121 |
| INSUFFICIENT_INFORMATION | 4 |
The two categories we actually care about are CODE_DUPLICATION (121 threads) and REDUNDANCY_REMOVAL (132 threads) — 253 threads in total. The other two labels are noise that the semantic filter removed.
A practical note: the model runs were parallelized (several threads classified concurrently).
Step 3: enrichment with Patchwork
We also want to know what happened to the thread. For that we queried Patchwork (patchwork.kernel.org), the tool that tracks the lifecycle of patches submitted to some kernel lists.
For each patchset (submission emails grouped by thread + patch version) we take the
last patch of the set and look it up by its message_id on
patchwork.kernel.org/api/patches/, filtering to the linux-iio project. Patchwork
returns a state string that we store in the accepted column. The column
is filled only on that last-patch row; every other row is left empty. When a message id
is not found in Patchwork, the value is also empty.
The states Patchwork reports:
- accepted — applied to the maintainer’s tree (the real “accepted”).
- mainlined — went further and was merged into mainline.
- rejected — the maintainer explicitly declined it.
- changes-requested — the maintainer asked for changes; the author must resend.
- superseded — replaced by a newer version (v2, v3…).
- not-applicable — does not apply to this subsystem/tree.
- handled-elsewhere — dealt with through another route/tree.
- new — submitted but not yet triaged.
Across the 424 patchsets we queried, the raw distribution was: changes-requested 130, (not found) 118, new 102, accepted 33, handled-elsewhere 21, superseded 16, rejected 2, not-applicable 1, mainlined 1.
Whenever we later need a single status per thread (a thread can contain several
versions with different states), we collapse it with a fixed priority that favors the
final outcome: accepted > mainlined > rejected > changes-requested > superseded >
not-applicable > handled-elsewhere > new. A thread is considered accepted when this
collapsed status is accepted or mainlined.
The final artifact of these three steps is iio-regex-classified-status.parquet: 7,600
rows, all original columns, plus duplication_classification and accepted.
Question 1
How many threads deal with duplication? This funnel answers it: out of the raw data, the regex + LLM pipeline leaves 253 threads that genuinely discuss duplication — 121 as code duplication and 132 as redundancy removal.

We also checked a course-specific curiosity: of the 429 threads, how many were
authored by someone with a USP e-mail (the original patch sender’s address matching
@usp.br / @ime.usp.br). The answer is 10 threads (2.3%).

Question 2
Of those patches, how many were accepted or rejected? For the duplication threads and the redundancy threads separately, this is the distribution of Patchwork outcomes. Each thread is reduced to a single collapsed status slice groups the threads whose patch was not indexed in Patchwork.
Already here we get a first hint that the answer is not a clean binary: outright
accepted and rejected are both rare, and most threads sit in intermediate states
(changes-requested, new) or have no recorded outcome at all

What we did here: collapsed each thread to one status;
is that outright rejected is rare — most non-accepted threads sit in
changes-requested and new, i.e. discussions that stalled rather than being formally refused.
Question 3
Question 3 asks to compare maintainers (accept vs reject) and ask whether the
decision is subjective. First we list who actually
shows up to review the duplication and redundancy threads. A “reviewer” here is a maintainer who
sent a reply (a Re: message), and we exclude replies from the
thread’s own author. People are grouped by name, because the same person appears under several e-mail addresses (Jonathan Cameron alone shows up with three). For each we report the number of distinct threads they appear in and their total number of replies.

The same handful of names dominate both categories — Jonathan Cameron, Andy Shevchenko, Lars-Peter Clausen, David Lechner, Greg KH — which is expected, since a subsystem is reviewed by a small, stable group of maintainers.
Analysis 3 — Acceptance rate per maintainer
Next we look at the reviewers’ outcomes. For each maintainer we compute
accepted threads / threads they participated in, split by category.
Important filtering choices for this chart:
- “Participated” means the maintainer sent a reply (a message with the response
tag, i.e. a
Re:) in that thread. Replies where the sender is the thread’s own author are excluded, so we count reviewers, not the submitter answering their own thread. - Maintainers are grouped by name, because the same person appears under several e-mail addresses (Jonathan Cameron alone shows up with three).
- Accepted = collapsed status in
{accepted, mainlined}. - The denominator counts only threads with a known status — threads whose patch was not found in Patchwork are excluded, so the rate is not diluted by unknowns.
- We show the top 5 maintainers by participation, computed within each category (so the two panels can have different people).

The absolute rates are low across the board, which already hints that these changes are hard to land regardless of who reviews them. And the acceptance rate varies from one maintainer to another even within the same category (e.g. in redundancy, Nuno Sá 23% vs David Lechner 9%). That variability is the first concrete sign that accept/reject is not a purely objective call — different reviewers converge on different outcomes.
Analysis 4 — Who has the last word
A different angle on the reviewers: in what fraction of the threads was each maintainer
the last non-author to reply — effectively, who tends to “close” these discussions.
We order every non-author reply by date and take the latest one per thread. The
denominator is the total number of threads in the category (121 / 132), and again we
show the top 5 by participation.

Jonathan Cameron — the IIO maintainer — has the last word in roughly half of every discussion, which matches his central role in the subsystem.
Analysis 5 — Themes of criticism (complement to Question 3)
This last analysis is a complement we added to make that concrete: what themes come up when a patch is refused? If the reasons for refusal were purely technical and objective (e.g. “it doesn’t compile”), we would expect them to look very different from a subjective, taste-based judgment such as “this is less readable”.
To find out, we looked at the language of the reviews —
the text of the maintainers’ replies in the non-accepted threads (collapsed status not in
{accepted, mainlined}), again excluding the threads’ own authors. Cleaning this text was
the hardest part and matters a lot for the result: we removed quoted lines (>),
automated CI messages (the kernel test robot), base64 blocks (undecoded MIME
parts), code/diff lines, and signatures (Best regards, Signed-off-by, …), plus
a stop-word list for reviewer names and generic filler.
Reading through those replies pointed at a hypothesis: maybe de-duplication is refused because reviewers find the result less readable. To test it we defined a small set of themes, each a group of keywords, and counted in how many threads the maintainers’ replies mention each theme. We did this for the non-accepted threads and, for comparison, for the accepted ones.
The four themes:
- Readability / clarity — readable, readability, clarity, clearer, harder/easier to read, obfuscate, obscure, confusing.
- Abstraction / indirection — abstraction, indirection, wrapper, helper, macro.
- Complexity — complex, complicated, convoluted, simpler, simplify, over-engineered.
- Maintainability — maintainable, maintainability, maintenance.
The metric per bar is the number of threads (not replies, to avoid over-counting verbose reviewers) in which the theme appears.
Non-accepted threads (372 with maintainer replies):

Accepted threads (33 with maintainer replies):

The comparison is the payoff of this complement. Readability is the single most common theme in the non-accepted threads (37%) — ahead of every other concern — and all of the “friction” themes are noticeably less frequent among the accepted ones (complexity 31% → 12%, abstraction 31% → 15%). This supports the hypothesis: when a reviewer brings up readability or complexity, the de-duplication change is less likely to land. And, tying back to question 3, “readability” and “clarity” are inherently subjective criteria — which is strong evidence that whether a de-duplication patch is accepted or rejected is, to a large extent, a matter of the reviewer’s judgment rather than a purely objective rule. The argument shows up in the raw replies:
“You will save a few repeated lines, but at the cost of driver readability.”
“I think we loose clarity to save few lines.”
“I don’t think this improves readability.”
Takeaways
Answering the three questions we started with:
- Q1 — How many threads deal with duplication? Out of 429 regex-matched threads, the LLM confirmed 253 as genuinely about duplication (121 code duplication + 132 redundancy removal); the rest were false positives.
- Q2 — How many were accepted or rejected? Removing duplicated code on a busy kernel
subsystem is hard to get merged, but the outcome is rarely a clean yes/no: outright
acceptedandrejectedare both rare, and most attempts stall in changes-requested / new or have no recorded Patchwork status at all. - Q3 — Comparing maintainers, is accept/reject subjective? Yes, largely. The acceptance rate varies from reviewer to reviewer even within the same category, and the most frequent reason reviewers push back is readability/clarity — a subjective criterion — more than complexity, abstraction, or maintainability, and that theme is markedly rarer in the threads that did get accepted.