Portál AbcLinuxu, 5. května 2025 23:21

Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian

6. 1. 2014 | Luboš Doležel
Články - Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian  

Aktuální verze jádra: 3.13-rc3. Citáty týdne: Rusty Russell, Mel Gorman. Oprava FS_IOC_GETFLAGS.

Obsah

Aktuální verze jádra: 3.13-rc3

link

Aktuální vývojová verze jádra je 3.13-rc3 vydaná 6. prosince. Linus k ní řekl: Stále dělám vydání v pátek, ale doufám, že se to brzy změní – důvod, proč jsem toto vydání neprotahoval do neděle, je ten, že to bylo už dost velké, a já počkám, než se to uklidní. Což by teď opravdu mělo. Ehm, ehm.

Stabilní aktualizace: verze 3.12.4, 3.10.23 a 3.4.73 byly vydány 8. prosince. V době psaní tohoto textu se verze 3.12.5, 3.10.24 a 3.4.74 revidují; jejich vydání lze očekávat 12. prosince nebo později.

Citáty týdne: Rusty Russell, Mel Gorman

link

"zpívání modulů" [singing vs. signing] zní jako příšerný nápad! Je autor vůbec hudebně nadaný? Slyšel jsem, že akorát říká David Vyje [Howls vs. Howells].

-- Rusty Russell

Pokud jsme Documentation/memory-barriers.txt nemohli ke strašení malých dětí používat dřív, tak teď už určitě můžeme.

-- Mel Gorman

Oprava FS_IOC_GETFLAGS

link

Vytváření jaderných rozhraní, která fungují na 32 i 64bitových procesorech, se ukázalo být dosti náročné. Jedinou z problémových oblastí je předávání argumentů do ioctl(), aby ten samý kód fungoval na obou typech procesorů – v big i little endian variantách. Nedávná diskuze ukázala, že ne všechny z těchto problémů se podařilo doposud vyřešit.

Aurelien Jarno poslal na mailing list linux-fsdevel otázku o FS_IOC_GETFLAGS a FS_IOC_SETFLAGS (které pracují s příznaků inodů souborů). Poznamenal, že definice těchto požadavků v include/uapi/linux/fs.h specifikuje typy argumentů jako ukazatele na long, až na verze pro 32bitovou kompatibilitu, kde se používá int *. Kód v jaderných systémech souborů očekává a používá 32bitovou kvantitu a většina – ale ne všechen – kódu v uživatelském prostoru předává ukazatel na 32bitové číslo.

Jakákoliv aplikace, která předá ukazatel na 64bitové číslo bude fungovat, ale jen na systémech little endian. Protože jaderný kód zachází s ukazatelem jako s odkazem na 32bitovou hodnotu, je pak otázkou, které čtyři bajty jsou při dereferencování použity. Na procesorech big-endian to jsou čtyři nejvýznamnější bajty, kdežto na procesorech little-endian to budou ty druhé čtyři bajty. Protože všechny příznaky jsou ve spodních čtyřech bajtech, tak systémy big-endian efektivně předávají do FS_IOC_SETFLAGS nulu nebo obdrží hodnotu s nedefinovaným obsahem vyšších bitů z FS_IOC_GETFLAGS.

Darrick J. Wong poukázal na to, že jaderný ovladač FUSE používá typy z tohoto hlavičkového souboru, což také zapříčiňuje problémy. Jaderný ovladač očekává přenos 64bitové kvantity, ale většina programů v uživatelském předává jen 32 bitů. Má v plánu speciálně ošetřit tyto požadavky ioctl() pro FUSE.

Množství big-endian 64bitových systémů (např. PowerPC, MIPS a s390) je oproti počtu little-endian x86-64 systémů opravdu malé. To znamená, že jen málo lidí mohlo zpozorovat problém, ale také to, že jakákoliv oprava se musí udělat opatrně tak, aby nedošlo k rozbití milionů stávajících systémů. To je u jádra vždy přednostně důležité, ale Ted Ts'o upozornil na tuto skutečnost, když vysvětloval, jak toto celé vzniklo a proč prostá změna na long * na všech místech nepomůže. Jelikož většina programů v uživatelském prostoru předává int *, tak by taková změna pravděpodobně vedla k rozbití na všech 64bitových systémech bez ohledu na endian.

Jarno ale zdůraznil, že kdokoliv se pokusí napsat kód správně a podívá se na typ argumentu v <linux/fs.h>, ten se se zlou potáže. Alespoň bychom mohli připsat upozornění blízko k definici vysvětlující, proč používat int a ne long.. Ukazuje se, že se tam nacházejí celkem čtyři požadavky ioctl() (ještě FS_IOC_GETVERSION a FS_IOC_SETVERSION kromě těch dříve zmíněných), které mají problematickou definici. Jarno zaslal patch, který tuto změnu uskutečňuje; konkrétně přidává do include/uapi/linux/fs.h (které se instaluje do include/linux) následující varování:

/*
 * VAROVÁNÍ: Následující čtyři ioctl přijímají ve skutečnosti jako argument int,
 * navzdory své definici. Toto je důležité pro podporu 64bitových big-endian
 * strojů.
 */

Človek by si mohl myslet, že prostá změna argumentu na 32 bitů v tomto hlavičkovém souboru by také byla možností, ale to se také nemůže udělat. Mapování názvu požadavku na číslo se provádí pomocí sady maker, která dělá sizeof() na argumentu „type“. Na 64bitových systémech to dělá osm pro long, ale na 32bitových to jsou čtyři. Protože jsou tato vypočítávaná čísla neměnnou součástí linuxového ABI, změna typu argumentu v tomto hlavičkovém souboru by problém nevyřešila.

Několik lidí navrhlo přidání nového typu požadavku (například FS_IOC_GETFLAGS_NEW nebo FS_IOC_GETFLAGS_WIDE). Přijímalo by ukazatel na 64bitové číslo na všech architekturách. To by mělo jako výhodu zdvojnásobení počtu možných příznaků, pro které teď už nemusí zbývat moc místa. Dnes jich zbývá asi tak deset, přidání dalších 32 by mohlo pokrýt budoucí potřeby, i když jiní nevěří, že 32 bude stačit.

Požadavky FS_IOC_[GS]ETFLAGS byly původně přidány pro systémy souborů ext*, ale časem je začaly používat i další systémy souborů. Kromě toho existují další příznaky pro jiné systémy souborů, které jsou dostupné jen přes ioctl(). Podle Davea Chinnera jich XFS má asi tak deset; další systémy souborů budou mít zase jiné vlastní příznaky. Takže když už děláme změnu, říká Chinner, proč neudělat takovou, která by sjednotila zacházení s těmito příznaky; udělalo by se to tak, aby se počítalo s více než 64 příznaky, které by se mohly brzy vyčerpat.

Ts'o není přesvědčen, že za to ta dodatečná složistost stojí. Ale Chinner předvídá přidání desítek nových příznaků inodů do XFS v dalších letech. Další systémy souborů mohou mít podobné potřeby. Proto není bitmapa o pevné délce nejlepším řešením z dlouhodobého hlediska, ale nepanovala zrovna shoda na tom, jaká alternativa by měla být zvolena.

Chinner navrhoval použít nějaké rozhraní postavené na atributech, které by bylo rozšiřitelné tak, aby ošetřovalo jakékoliv příznaky inodů na jakýchkoliv systémech souborů. Jako další možnost zmínil systémové volání xstat(). Jenže Andreas Dilger upozornil na to, že xstat() už bylo navrhováno mnohokrát, ale nikdy se do jádra nedostalo.

Takže tu máme možná řešení, která vyřeší problém jednou provždy (jak to popsal Chinner), ale není jasné, jestli má někdo úmysl protlačovat jedno z nich. Mezitím Jarnova „oprava“ v hlavičkovém souboru alespoň pomůže uživatelům předávat správný typ argumentu. Aplikace, jež předávají ukazatel na long (byly zmíněny bup a libexplain) se musí změnit, ale to by nemělo být tak těžké. Lepší, celkové řešení nemusí být hotové v dohledné době.

Odkazy a zdroje

Kernel coverage at LWN.net: December 12, 2013

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

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

Diskuse k tomuto článku

6.1.2014 09:43 Petr Ježek | skóre: 10
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Odpovědět | Sbalit | Link | Blokovat | Admin
Musím říci, že FS_IOC_[GS]ETFLAGS velmi svědčí EXT FS, protože jejich funkčnost nijak neovlivňuje rychlost či jiné funkce. Pro příznaky je logicky ještě dost prostoru.
Archlinux for your comps, faster running guaranted!
6.1.2014 15:54 Sten
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Odpovědět | Sbalit | Link | Blokovat | Admin
Pokud makro mapující ioctl dělá sizeof, co je na tom těžkého poznat, jestli je parametr int nebo long?
6.1.2014 18:48 petr_p | skóre: 59 | blog: pb
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
No třeba na n32 MIPS64 má v GCC int i long 4 bajty.
6.1.2014 20:06 Sten
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Pokud má oboje 4 bajty, pak je jedno, jestli se to čte jako int nebo long, protože výsledek bude stejný ;-) Mluvil jsem o těch problémech popsaných v článku, kde 4bajtový int předaný z user space se v jádře čte jako 8bajtový long nebo obráceně.
6.1.2014 21:26 petr_p | skóre: 59 | blog: pb
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Jenže v tomto případě je jádro plně 64bitové a tam int má 4 B a long 8 B. A když vezmeme v úvahu, že MIPS se dělá jak little tak big endian, tak máme problém.
6.1.2014 22:23 Sten
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
A to by právě řešilo to sizeof, ne?
7.1.2014 07:26 finn | skóre: 43 | blog: finnlandia | 49° 44´/13° 22´
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Jestli chápu situaci dobře, předává se ukazatel (to je důležité) na int resp. long int. Ale z ukazatele (tj. adresy) informaci o velikosti odkazované proměnné nelze získat.
Užívej dne – možná je tvůj poslední.
7.1.2014 12:45 Sten
Rozbalit Rozbalit vše Re: Jaderné noviny – 12. 12. 2013: Skryté chyby na big endian
Jj, už to vidím v manuálové stránce, dělá se tam sizeof na argp, což je ukazatel, čímž se sice odliší, jestli je to 32 bit nebo 64 bit, ale už se nezjistí, jestli je tam int nebo long.

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