Portál AbcLinuxu, 26. dubna 2024 07:09

Jaderné noviny – 26. 9. 2013: Když ABI nejde nerozbít

14. 10. 2013 | Luboš Doležel
Články - Jaderné noviny – 26. 9. 2013: Když ABI nejde nerozbít  

Aktuální verze jádra: 3.12-rc2. Citáty týdne: Linus Torvalds, Andrew Morton, James Mickens. Garrett: Implementace bootování do Zorku přes UEFI. NVIDIA poskytne dokumentaci projektu Nouveau. Oprava ABI v perf.

Obsah

Aktuální verze jádra: 3.12-rc2

link

Aktuální vývojová verze jádra je 3.12-rc2 vydaná 23. září. Linus k ní řekl: Nedělo se nic divokého, snad i díky tomu, že hodně lidí cestovalo minluý týden na LinuxCon a Linux Plumbers conference. Proto se tu neobjevuje nic zrovna vzrušujícího. Jde hlavně o aktualizace/opravy ovladačů (hlavně ovladače GPU, ale i sítě a menší věci všude okolo). Kromě ovladačů jsou tu i aktualizace v architekturách (tile/arm/mips) a drobnosti v systémech souborů (hlavně btrfs).

Stabilní aktualizace: minulý týden žádné nevyšly. Verze 3.11.2, 3.10.13, 3.4.63 a 3.0.97 se aktuálně revidují; jejich vydání lze očekávat 27. září nebo později.

Citáty týdne: Linus Torvalds, Andrew Morton, James Mickens

link

Vypadá to, že bych si měl víc hlídat, kdy má Andrew závody.

-- Linus Torvalds plánuje příští začleňovací okno

Mor na toho, kdo vymyslel velké stránky. Slovy nelze popsat, jaký strašný bordel je kvůli nim ve správě paměti v Linuxu. A ještě tomu není konec.

-- Andrew Morton

John hledal ve výzkumné literatuře nápady, které by vyřešily jeho sny o nekonečném škálování. Našel několik dokumentů, které popisují obnovu hardwaru po selhání za asistence softwaru. Základní myšlenka byla prostá: pokud hardware trpí více přechodnými chybami s tím, jak se zmenšuje, proč neumožnit softwaru odhalit chybné výpočty a zopakovat je? Myšlenka se to zdála být dobrá, než si John uvědomil, ŽE TO JE TEN NEJHORŠÍ NÁPAD NA SVĚTĚ. Moderní software stěží funguje, když hardware pracuje správně, takže spoléhat se při opravování hardwarových chyb na software je jako žádat Godzillu, aby zabránila Mega-Godzille terorizovat Japonsko. TOTO NEVEDE KE ZVYŠOVÁNÍ HODNOT NEMOVITOSTÍ V TOKYU.

-- James Mickens [PDF]

Garrett: Implementace bootování do Zorku přes UEFI

link

Matthew Garrett konečně implementoval to, oč nám šlo především: přímé bootování do hry Zork z UEFI. Navzdory tomu, že má funkce připomínající spíše OS než bootovací prostředí, UEFI neposkytuje standardní knihovnu jazyka C. EFI Application Development Kit toto konkrétní návrhové rozhodnutí řeší.

NVIDIA poskytne dokumentaci projektu Nouveau

link

Nouveau je ovladač pro GPU NVIDIA vzniklý pomocí zpětného inženýrství; vyvíjí se už řadu let bez pomoci od NVIDIA. Nyní se ale na mailing listu Nouveau objevil vývojář NVIDIA s nabídkou pomoci: NVIDIA zveřejňuje dokumentaci některých vlastností našich GPU s cílem zaměřit se na oblasti, které mají dopad na použitelnost GPU NVIDIA s Nouveau. Naším plánem je postupně zveřejňovat více dokumentace a poskytovat pomoc v oblastech, kde můžeme být ku pomoci. Toto vypadá jako velký krok správným směrem.

Oprava ABI v perf

link

Často se opakuje, že se vývojáři musí vyhýbat porušení kompatibility ABI za každou cenu. Problémům s ABI se ale někdy obtížně vyhýbá. Někteří říkají, že rozhraní událostí perf je obzvláště náchylné k nekompatibilním změnám v ABI, jelikož nástroj perf je součástí jaderného stromu; protože se perf může vývíjet společně s jádrem, je tu riziko, že si vývojáři porušení kompatibility ani nevšimnou. Nedávné odhalení problému v ABI perfu proto stojí za pozornost jako příklad toho, jak jsou problémy s kompatibilitou v tomto kódu řešeny.

Systémové volání perf_event_open() vrací popisovač, který mimo jiné může být použit k mapování kruhového bufferu do adresního prostoru procesu pomocí mmap(). První stránka tohoto bufferu obsahuje různé informace pro správu dat vyjádřené pomocí struct perf_event_mmap_page definované v <uapi/linux/perf_event.h>. V této struktuře (v jádře 3.11) najdeme následující kus kódu:

union {
	__u64	capabilities;
	__u64	cap_usr_time  : 1,
		cap_usr_rdpmc : 1,
		cap_____res   : 62;
};

Zvědavým napovíme, že cap_usr_rdpmc indikuje, že uživatelskému prostoru je přímo přístupná instrukce RDPMC (která získává údaje ze monitorovacích čítačů přímo), a cap_usr_time zase značí, že čítač časového razítka lze číst pomocí RDTSC. Pokud jsou tyto funkce (popsané jako „capabilities“, i když nemají nic společného s capabilities používanými v jádře pro bezpečnost) dostupné, pak kód, který sleduje sám sebe, může přestat používat jádro jako prostředníka a číst údaje přímo.

Význam výše uvedené deklarace je jasný: vývojáři chtěli mít možnost pracovat s úplnou sadou vlastností jako s jedinou kvantitou nebo moci přistupovat k jednotlivým bitům přes pole cap_. Není třeba se na kód dívat moc dlouho, abyste našli chybu: každé z polí cap_ je samostatným prvkem v unionu, takže budou mapována na ten samý bit. Toto rozhraní proto nikdy nefungovalo tak, jak mělo. Jako ukázka důslednosti revidování kódu poslouží to, že kód byl zařazen v Linuxu 3.4 a vydržel tam až do Linuxu 3.11.

Jakmile problém někdo zaznamenal, tak Adrian Hunter rychle zaslal předvídatelnou opravu v podobě shulknutí polí cap_ do oddělené struktury. Netrvalo dlouho a Vince Weaver nalezl nový problém: kód, který fungoval s rozbitou definicí struktury, už nefunguje s opravenou verzí. Oprava přesunula cap_usr_rdpmc z bitu 0 na bit 1 (a cap_usr_time zůstalo na bitu 0) s tím důsledkem, že binárky sestavené pro starší jádro jej hledají na špatném místě. Pokud je zase program sestaven s novou definicí, tak při běhu na starém jádře také hledá toto pole na špatném místě a dochází tak ke špatnému závěru.

Po krátké diskuzi už bylo jasné, že nebude možné opravit problém zcela transparentně nebo opravu skrýt před novým kódem. Pak Peter Zijlstra navrhl, že by se mohlo použít pole s verzí; aplikace by mohly explicitně ověřovat verzi ABI a podle toho se zachovat. To ale Ingo Molnar zavrhl jako opravdu křehké a přišel s vlastním řešením. Po několika kolech debat vypadal union takto:

union {
 	__u64	capabilities;
 	struct {
		__u64 cap_bit0          : 1,
	    	  cap_bit0_is_deprecated: 1, 
	    	  cap_user_rdpmc        : 1,
	    	  cap_user_time         : 1,
	    	  cap_user_time_zero    : 1,
	    	  cap_____res           : 59;
 	};
};

V novém ABI je cap_bit0 vždy nastaven na nulu, zatímco cap_bit0_is_deprecated je vždy jedna. Proto může kód znalý této změny ověřit hodnotu cap_bit0_is_deprecated pro zjištění, jakou verzi rozhraní používá; pokud detekuje novou verzi jádra, bude vědět, že různá pole cap_user_ (změněno z cap_usr_) jsou platná a je možné je používat. Kód sestavený pro stará jádra zase uvidí všechny původní hodnoty (obě namapované na bit 0) jako nastavené na nulu. (Pro zajímavost, nové pole cap_user_time_zero bylo přidáno v nezávisle vzniklé změně ve verzi 3.12.)

Někdo by mohl namítat, že tato změna stále představuje rozbití ABI, jelikož starý kód dospěje k závěru, že RDPMC je nedostupné, i pokud ve skutečnosti je podporované. Takový kód nebude fungovat tak dobře, jako by fungoval na starém jádře. Ale bude se chovat správně, o což jde především. Otravnější je ta skutečnost, že kód napsaný pro jednu verzi rozhraní nepůjde zkompilovat s druhou; jde o rozbití API, ačkoliv ABI nadále funguje. Toto bude nepochybně otravné pro některé uživatele nebo balíčkáře, ale bylo to vnímáno jako lepší řešení, než nadále používat rozhraní, o kterém se ví, že je rozbité. Vince Weaver, který byl někdy kritický ke správě ABI perfu, uznal, že toto je asi to nejrozumnější řešení, které jsme mohli vymyslet.

Další důležitou vlastností této změny je to, že struktura sama popisuje, jak se mají bity chápat. Vývojáře to mohlo svádět k tomu, aby jen udělali změnu a někde zdokumentovali, že od verze 3.12 je nutné používat nové bity. Ale tento typ poznámky je moc snadné přehlédnout nebo zapomenout zohlednit, a to i v takto jednoduchém případě. Pokud by oprava byla backportována do stabilních jader, tak by dokonce ani jednoduchá kontrola verze nemusela stačit. Díky speciálnímu bitu cap_bit0_is_deprecated může kód zjistit, jak má reagovat, nezávisle na tom, v jaké verzi se oprava objeví.

Abychom to shrnuli, tak si lze těžko stěžovat na to, že by vývojáři perfu nebrali v tomto případě na ABI ohled. Ke změně API dojde ve verzi 3.12 (předpokládejme, že Ingův patch bude zařazen, což se zatím nestalo), ale všechny kombinace nových a starých jader a aplikací budou nadále fungovat; k tomuto rozbití ABI došlo během začleňovacího okna 3.12, ale nikdy se to nedostalo do stabilních jader. Klíčem je zde brzké testování; tím, že Vince problém odchytil hned na začátku vývojového cyklu, umožnil, že k opravě došlo ještě před stabilním vydáním. Vývojáři jádra nechtějí vytvářet problémy s ABI, ale rozsáhlé testování vývojových jader je nezbytnou součástí procesu, který rozbití ABI brání.

Odkazy a zdroje

Kernel coverage at LWN.net: September 26, 2013

Další články z této rubriky

Jaderné noviny – přehled za březen 2024
Jaderné noviny – přehled za únor 2024
Jaderné noviny – přehled za leden 2024
Jaderné noviny – přehled za prosinec 2023
Jaderné noviny – přehled za listopad 2023

Diskuse k tomuto článku

14.10.2013 08:58 Pepa
Rozbalit Rozbalit vše Re: Jaderné noviny – 26. 9. 2013: Když ABI nejde nerozbít
Odpovědět | Sbalit | Link | Blokovat | Admin
V čem/s čím Andrew závodí?
Bedňa avatar 15.10.2013 15:02 Bedňa | skóre: 34 | blog: Žumpa | Horňany
Rozbalit Rozbalit vše Re: Jaderné noviny – 26. 9. 2013: Když ABI nejde nerozbít
Race condition, Race in sem_lock()?
KERNEL ULTRAS video channel >>>
14.10.2013 15:27 Sten
Rozbalit Rozbalit vše Re: Jaderné noviny – 26. 9. 2013: Když ABI nejde nerozbít
Odpovědět | Sbalit | Link | Blokovat | Admin

Rozbití API lze řešit ještě snáze:
#define PERF_CAP_BIT0_DEPRECATED_PRESENT

Nakonec k takovému rozbití API dochází v každé nové verzi jádra :-)

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.