En gren som talar om vem som skrev den

En gren som heter noref-filemap-read-with-llm dök upp i Linus Torvalds egen kernelträd i helgen. Den innehåller åtta patchar, alla skrivna och incheckade av Torvalds den 9 och 10 oktober, ovanpå 7.3-rc6. Den sista är en tom incheckning som bär ingenting annat än förklaringen, och nära slutet av den texten, under rubriken “Tools”, står ett stycke som få kernelincheckningar innehåller:

“Koden, testprogrammen, granskningen bakom listan ovan och det första utkastet till den här texten gjordes med en LLM-baserad kodassistent (Claude Code) under min ledning. Mätningarna kördes på min egen maskin.”

Phoronix, som hittade grenen i väntan på 7.3-rc7, påpekade att Torvalds sällan håller arbetsgrenar i sitt huvudrepositorium över huvud taget. De åtta incheckningarna finns inte i master, och han har inte sagt om de ska in i sammanslagningsfönstret för 7.4.

En whiteboardtavla full av handritade diagram på ett kontor
Torvalds uppger att koden, testprogrammen och granskningen gjordes med en assistent under hans ledning. Illustrationsbild. Christina Morillo · pexels · Pexels License

Problemet är en cache-rad

Serien angriper ett konkurrensproblem som Matthew Wilcox tog upp 2024 utifrån en kunds arbetslast. När många trådar läser små mängder ur samma fil tar och släpper varje läsning en referens på det folio som håller sidan, så varje läsning skriver samma cache-rad i struct page två gånger. På Torvalds bärbara dator — en i7-8565U med fyra kärnor och åtta trådar — lägger åtta trådar som gör 16 byte stora pread()-anrop mot en enda sida 99,92 procent av alla load-HITM:ar på just den raden.

Hans lösning är att inte ta referensen alls. Ett folio som tas bort ur sidcachen går nu tillbaka till sidallokatorn först efter en RCU-nådperiod, vilket betyder att en sida som hittas under rcu_read_lock() fortfarande håller filens data tills låset släpps. Läsningen kopierar sedan rakt in i användarbufferten med sidfel avstängda: ingen referens, ingen mellanbuffert på stacken, ingen kontroll efter kopieringen och ingen gräns för läsningens storlek.

Tidigare försök, skriver Torvalds, kopierade utan referens till en stackbuffert och validerade efteråt, och “stannade vid det valideringen inte kan se”: frigörande, återanvändning och återinsättning på samma index, migrering, och läsning av minne som inte är sidcache alls, däribland secretmem, icke godtaget minne och “eller ännu värre MMIO med oönskade läseffekter”. Att skjuta upp frigörandet tar bort de fallen i stället för att upptäcka dem.

Tre gånger så många läsningar, och 30 538 HITM:ar ned till 101

Siffrorna i incheckningsmeddelandet kommer från en enda maskin, med ext4 och med CPU-motåtgärder och CONFIG_HARDENED_USERCOPY avstängda. Med åtta trådar som läser 16 byte ur en sida klarar baskärnan 9,9 till 10,4 miljoner läsningar i sekunden vid 2 937–2 975 kernelcykler per läsning. Med serien klarar den 30 till 33 miljoner vid 725–726 cykler. Fyra trådar, en per kärna, går från 8,9–11,6 miljoner till 25–26 miljoner. Load-HITM:ar mätta med perf c2c faller från 30 538 till 101.

En trave hårddiskar på ett skrivbord
Konkurrensen serien angriper uppstår när många trådar läser små mängder ur samma fil. Illustrationsbild. Marta Branco · pexels · Pexels License

Priset är minne som står i kö och väntar på en nådperiod, och det är den del Torvalds kallar minst löst. Wilcox invändning mot att skjuta upp frigörandet, citerad i meddelandet, var att “det känns helt enkelt för riskabelt att ha så mycket minne som väntar på att återanvändas”. Patch 7 och 8 finns för att hålla det i schack: över 1 024 väntande sidor på en CPU anropar ett andra arbetsobjekt synchronize_rcu_expedited() och frigör listan, vilket med fyra processer som stansar hål sker 4 600 gånger i sekunden — något som funktionens egen dokumentation säger att man inte ska göra i en loop. Torvalds flaggar det själv: “Finns det ett sätt att få en kort nådperiod utan dem?”

Vad han säger att han inte har testat

Meddelandet avslutas med en lista över vad serien inte har körts mot: minnestryck utöver ett enda testfall i en virtuell maskin, lockdep, KASAN, en kärna byggd med clang, 32-bitar, CONFIG_HARDENED_USERCOPY och “någon annan maskin än den här”. Om schemaläggarändringen i patch 8 skriver han: “Jag är inte säker på att det här är rätt riktning; jag skulle hellre se att den frigörande uppgiften gjorde något synkront som lämnar schemaläggaren i fred.”

Det är den delen som är värd att följa, snarare än verktyget. Torvalds har publicerat en prestandakritisk minneshanteringsserie, tillskrivit koden en assistent, behållit mätningarna för sig själv och lämnat två öppna frågor till underhållarna av delsystemen. Om den överlever granskningen på sändlistan är ett annat prov än om den sprang fort på hans bärbara dator.