Nästa Föregående Innehållsförteckning

6. Konsekvenser

Vad betyder allt det här? För Linuxanvändare bara en sak: att de måste se till att LILO och fdisk använder rätt geometri där "rätt" för fdisk är definierat som geometrin som används av de andra operativsystemen på samma hårddisk, och "rätt" för LILO definieras som geometrin som möjliggör lyckad interaktion med BIOSet vid uppstart. (Normalt sett sammanfaller dessa.)

Hur känner fdisk till geometrin? Den frågar kärnan genom att använda ioctl:n HDIO_GETGEO. Men användaren kan själv, interaktivt eller på kommandoraden, bestämma vilken geometri som ska användas.

Hur känner LILO till geometrin? Den frågar kärnan genom att använda ioctl:n HDIO_GETGEO. Men användaren kan själv, med hjälp av parametern "disk=", bestämma vilken geometri som ska användas. Man kan också ge parametern "linear" till LILO, som då kommer att lagra LBA-adresser istället för CHS-adresser i sin map-fil och räkna ut vilken geometri som ska användas vid uppstart (genom att använda INT 13 funktion 8 för att fråga om hårddiskgeometrin).

Hur vet kärnan vad den ska svara? Jo, användaren kan explicit ha specificerat en geometri med en parameter som hd=cyls,heads,secs. Annars frågar kärnan hårdvaran.

6.1 IDE-detaljer

Låt mig utveckla mig. IDE-drivrutinen har fyra källor för information om geometrin. Den första (G_user) är den som användaren kan ha specificerat på kommandoraden. Den andra (G_bios) är BIOS' parametertabell (för fixa hårddiskar; bara för den första och den andra hårddisken) som läses innan bytet till 32-bitarsmod. Den tredje (G_phys) och fjärde (G_log) returneras av IDE-kontrollern som ett svar på kommandot IDENTIFY -- de är de "fysiska" och "nuvarande logiska" geometrierna.

Å andra sidan behöver drivrutinen två värden för geometrin: för det första G_fdisk, som returneras av en HDIO_GETGEO-ioctl, och för det andra G_used, som faktiskt används för I/O. Både G_fdisk och G_used initialiseras till G_user om den är given, till G_bios om informationen finns tillgänglig enligt CMOS, och annars till G_phys. Om G_log verkar vara rimlig sätts G_used till det. Annars, om G_used inte verkar rimlig och G_phys ser rimlig ut, sätts G_used till G_phys. Här betyder "rimlig" att antalet huvuden ligger i intervallet 1-16.

Med andra ord: kommandoraden har högre prioritet än BIOSet och bestämmer vad fdisk ser, men om det specificerar en översatt geometri (med fler än 16 huvuden) kommer det som returneras från IDENTIFY-kommandot att användas för kärn-I/O.

6.2 SCSI-detaljer

Situationen för SCSI är något annorlunda, eftersom SCSI-kommandona redan använder logiska blocknummer, så en "geometri" är helt irrelevant för I/O i praktiken. Formatet för partitionstabellen är emellertid fortfarande samma, så fdisk måste uppfinna en geometri och använder HDIO_GETGEO här också -- faktiskt skiljer inte fdisk på IDE- och SCSI-hårddiskar. Som man kan förstå från den detaljerade beskrivningen nedan, uppfinner de olika drivrutinerna en något annorlunda geometri. Helt klart en sagolik röra.

Om du inte använder DOS eller så, undvik alla inställningar rörande utökad översättning och använd bara 64 huvuden, 32 sektorer per spår (vilket ger trevliga 1 MB per cylinder), om möjligt, så att inga problem uppstår när du flyttar hårddisken från en kontroller till en annan. Vissa drivrutiner för SCSI-hårddiskar (aha152x, pas16, ppa, qlogicfas, qlogicisp) är så måna om att bibehålla DOS-kompatibilitet att de inte tillåter ett system som bara kör Linux att använda mer än 8 GB. Detta är en bugg.

Vad är den riktiga geometrin? Det lättaste svaret är att det inte finns någon sådan. Och om det fanns skulle du inte vilja vet något om den och säkerligen ALDRIG NÅGONSIN tala om den för fdisk eller LILO eller kärnan. Det är endast relevant för SCSI-kontrollern och hårddisken. Låt mig upprepa: bara dumma personer talar om den riktiga geometrin för en SCSI-hårddisk för fdisk/LILO/kärnan.

Men om du är nyfiken och insisterar kan du fråga hårddisken själv. Det finns det viktiga kommandot READ CAPACITY som ger den totala storleken på hårddisken och det finns kommandot MODE SENSE som i "Rigid Disk Drive Geometry Page" (sida 04) ger antalet cylindrar och huvuden (detta är information som inte går att ändra), och "Format Page" (sida 03) ger antal byte per sektor och antal sektorer per spår. Det sistnämnda antalet är typiskt beroende av notchen och antalet sektorer per spår varierar -- de yttre spåren har fler sektorer än de inre. Linuxprogrammet scsiinfo kan ge den här informationen. Det finns många detaljer och komplikationer och det står klart att ingen (inte ens operativsystemet) vill använda denna information. Dessutom: så länge man enbart bryr sig om fdisk och LILO får man typiskt svar som C/H/S=4476/27/171 -- värden som inte kan användas av fdisk eftersom partitionstabellen endast reserverar 10 respektive 8 respektive 6 bitar för C/H/S.

Så var får kärnanropet HDIO_GETGEO sin information från? Jo, antingen från SCSI-kontrollern eller genom att göra en kvalificerad gissning. Några drivrutiner verkar tro att vi vill känna till "verkligheten", men självklart vill vi bara veta vad FDISK i DOS eller OS/2 (eller Adaptecs AFDISK, etc) kommer att använda.

Notera att Linux' fdisk behöver talen H och S (för huvuden och sektorer) för att kunna konvertera LBA-sektornummer till C/H/S-adresser, men talet C (cylindrar) spelar ingen roll i den här konverteringen. Några drivrutiner använder (C,H,S) = (1023,255,63) för att signalera att hårddiskkapaciteten är minst 1023*255*63 sektorer. Detta är olyckligt, eftersom det inte avslöjar den riktiga storleken, vilket kommer att begränsa användarna av de flesta fdisk-versionerna till att använda 8 GB av sina hårddiskar -- en riktig begränsning i dessa dagar.

I beskrivningen nedan står M för den totala hårddiskkapaciteten och C, H, S för antalet cylindrar, huvuden och sektorer per spår. Det räcker att ge H, S om vi betraktar C som definierad av M / (H*S).

Standardmässigt är H=64, S=32.

aha1740, dtc, g_NCR5380, t128, wd7000:

H=64, S=32.

aha152x, pas16, ppa, qlogicfas, qlogicisp:

H=64, S=32 om inte C > 1024, då H=255, S=63, C = min(1023, M/(H*S)). (Alltså trunkeras C och H*S*C är inte en approximation för hårddiskkapaciteten M. Detta gör de flesta fdisk-versioner förvirrade.) Koden i ppa.c använder M+1 istället för M och säger på grund av en bugg i sd.c att M är ett för lite.

advansys:

H=64, S=32 om inte C > 1024 och "> 1 GB" är inställt i BIOS, då H=255, S=63.

aha1542:

Fråga kontrollern vilket av två möjliga sätt att översätta på som ska användas och använd antingen H=255, S=63 eller H=64, S=32. I det första fallet blir det ett boot-meddelande: "aha1542.c: Using extended bios translation".

aic7xxx:

H=64, S=32 om inte C > 1024 och antingen boot-parametern "extended" gavs eller att biten "extended" var satt i SEEPROM eller BIOS, då H=255, S=63.

buslogic:

H=64, S=32 om inte C >= 1024, och om utökad översättning är inställt på kontrollern, så är H=128, S=32 om M < 2^22, annars H=255, S=63. Efter att detta val har gjorts läses partitionstabellen och om värdet endH=H-1 syns för någon av de tre möjligheterna (H,S) = (64,32), (128,32), (255,63), blir det ett boot-meddelande: "Adopting Geometry from Partition Table".

fdomain:

Ta reda på geometriinformationen från parametertabellen för hårddiskar i BIOS eller läs partitionstabellen och använd H=endH+1, S=endS för den första partitionen, ifall den inte var tom, annars: använd H=64, S=32 för M < 2^21 (1 GB), H=128, S=63 för M < 63*2^17 (3,9 GB) och H=255, S=63.

in2000:

Använd den första av (H,S) = (64,32), (64,63), (128,63), (255,63) som gör att C <= 1024. I det sista fallet, trunkera C vid 1023.

seagate:

Läs C,H,S från hårddisken. (Iiiick!) Om C eller S är för stor, sätt S=17, H=2 och dubbla H tills C <= 1024. Detta innebär att H kommer att sättas till 0 om M > 128*1024*17 (1,1 GB). Detta är en bugg.

ultrastor och u14_34f:

En av tre mappningar ((H,S) = (16,63), (64,32), (64,63)) används beroende på kontrollerns mappningsmod.

Om drivrutinen inte specificerar geometrin använder vi en kvalificerad gissning genom att använda partitionstabellen eller genom att använda den totala hårddiskkapaciteten.

Kolla på partitionstabellen. Eftersom, per konvention, partitioner slutar på en cylindergräns kan vi, givet end = (endC,endH,endS) för vilken partition som helst, helt enkelt sätta H = endH+1 och S = endS. (Kom ihåg att sektorerna räknas från 1.) Mer precist görs följande: Om det finns en icke-tom partition, välj den partition med störst beginC. Titta på end+1 för den partitionen, beräknat genom att både addera start och length och genom att anta att partitionen slutar på en cylindergräns. Om båda värdena stämmer överens eller om endC = 1023 och start+length är en heltalsmultipel av (endH+1)*endS, anta att partitionen faktiskt var placerad på en cylindergräns och sätt H = endH+1 och S = endS. Om detta inte fungerar, antingen på grund av att det inte finns några partitioner eller på grund av att de har konstiga storlekar, kolla bara på hårddiskkapaciteten M. Algoritm: sätt H = M/(62*1024) (avrundat uppåt), S = M/(1024*H) (avrundat uppåt), C = M/(H*S) (avrundat neråt). Detta ger en (C,H,S) med C högst 1024 och S högst 62.


Nästa Föregående Innehållsförteckning