Le gestionnaire IDE a cinq sources d'information concernant la géométrie. La première (G_user) est celle donnée par l'utilisateur sur la ligne de commande. La deuxième (G_bios) est la `BIOS Fixed Disk Parameter Table' - table des paramètres de disque fixe du BIOS - (pour le premier et second disque dur seulement) qui est lue au démarrage du système, avant le passage au mode 32 bits. Les troisième (G_phys) et quatrième (G_log) sont données par le contrôleur IDE en réponse à la commande IDENTIFY - ce sont les géométries `physique' et `logique du moment'.
D'un autre côté, le gestionnaire a besoin de deux valeurs pour la géométrie :
d'abord G_fdisk, donnée par un ioctl HDIO_GETGEO
, et ensuite G_used, qui
est effectivement utilisée pour les Entrées/Sorties. G_fdisk et G_used sont
toutes deux initialisées avec la valeur de G_user si elle est fournie, avec
G_bios quand le CMOS dit que cette valeur est présente, et avec G_phys
autrement. Si G_log semble vraisemblable, alors G_used est positionnée à cette
valeur. Sinon, si G_used n'est pas vraisemblable et que G_phys semble
l'être, alors G_used prend la valeur de G_phys. Ici, `vraisemblable'
signifie que le nombre de têtes est compris dans l'intervalle 1-16.
En d'autres termes : la ligne de commande prend le pas sur le BIOS et va
déterminer ce que va voir fdisk
, mais si elle donne une géométrie
convertie (avec plus de 16 têtes), alors pour les Entrées/Sorties
qu'effectuera le noyau elle sera elle-même remplacée par les valeurs
que fournira la commande IDENTIFY.
Remarquez que G_bios est assez peu fiable : pour des systèmes qui démarrent depuis un périphérique SCSI, les premier et second disques durs peuvent très bien être SCSI ; et la géométrie que le BIOS aura donné pour sda sera utilisée par le noyau pour hda. Du reste, les disques durs qui ne sont pas déclarés dans la configuration du BIOS ne sont pas vus par ce dernier. Cela signifie que, par exemple, dans un système uniquement IDE où hdb n'est pas déclaré dans la configuration, les géométries rapportées par le BIOS pour les premier et second disques vont être appliquées à hda et hdc.
La situation pour le SCSI est légèrement différente, puisque les commandes
SCSI utilisent déjà les numéros de blocks logiques, donc une `géométrie' est
complètement hors de propos pour les véritables Entrées/Sorties.
Cependant, le format de la table des partitions est toujours le même,
donc fdisk
ne fait pas la différence entre des disques IDE et SCSI.
Comme on peut le voir à partir de la description détaillée ci-dessus, chaque
gestionnaire de disques s'invente une géométrie différente. Un gros foutoir
en fait.
Si vous n'utilisez pas DOS ou un équivalent, alors évitez toute configuration qui met en jeu des conversions étendues, et utilisez simplement 64 têtes, 32 secteurs par piste (cela a pour effet de donner une valeur tout à fait sympathique et commode de 1Mio par cylindre), si possible, comme ça il n'y aura pas de problème quand vous déplacerez le disque dur d'un contrôleur à un autre. Certains gestionnaires de disque SCSI (aha152x, pas16, ppa, qlogicfas, qlogicisp) sont si sensibles au sujet de la compatibilité avec le DOS qu'ils ne permettront pas à un système uniquement Linux d'utiliser plus de 8 Gio. C'est un bug.
Quelle est la vraie géométrie ?
La réponse la plus facile est qu'elle n'existe pas.
Et si elle existait, vous ne voudriez pas la connaître, et à coup sûr
JAMAIS, AU GRAND JAMAIS ne devrez en dire quoi que ce soit à fdisk
ou à
LILO ou au noyau.
C'est uniquement une histoire entre le contrôleur SCSI et le disque dur.
Laissez-moi le redire : seules les personnes stupides donnent à
fdisk
, à LILO ou au noyau la véritable géométrie d'un disque SCSI.
Mais si vous êtes curieux et que vous insistez, vous devez demander au disque
dur lui-même. Il y a l'importante commande READ CAPACITY qui donnera la
capacité complète du disque dur, et il y a la commande MODE SENSE, qui, dans
la Rigid Disk Drive Geometry Page (page 04) donne le nombre de cylindres et
de têtes (c'est une donnée qui ne peut pas être changée), et dans
la Format Page (page 03) donne le nombre d'octets par secteur, et de secteurs
par piste. Ce dernier nombre est typiquement dépendant du rang, et le nombre
de secteurs par piste varie - les pistes extérieures ont plus de secteurs que
les pistes intérieures. Le programme Linux scsiinfo
donnera cette
information. Il y a de nombreux détails et complications, et il est clair que
personne (probablement même pas le système d'exploitation) ne désire
utiliser cette information. Du reste, tant que nous ne nous intéressons quà
fdisk
et à LILO, on a typiquement des réponses du style
C/H/S=4476/27/171 - valeurs qui ne peuvent pas être utilisées par
fdisk
parce que la table des partitions ne réserve que 10,8 et 6 bits pour
respectivement C/H/S.
Mais alors, d'où le HDIO_GETGEO
du noyau tire-t-il ses informations ?
Et bien, soit du contrôleur SCSI, soit en faisant une supposition éclairée.
Certains gestionnaires de disque semblent croire que nous voulons
connaître la `réalité', mais bien sûr nous ne voulons savoir que ce que
FDISK de DOS ou de OS/2 (ou AFDISK de Adaptec, etc...) utiliseront.
Remarquez que le fdisk
de linux a besoin des nombres H et S de
têtes et de secteurs par piste pour convertir les nombres de secteurs
LBA en adresses c/h/s, mais le nombre de cylindres C ne joue aucun
rôle. Quelques gestionnaires de disque utilisent (C,H,S) =
(1023,255,63) pour signaler que la capacité du disque dur est d'au moins
1023*
255*
63 secteurs. Ce n'est pas de chance, puisqu'ils ne
révèlent pas la vraie taille, et limiteront les utilisateurs de la plupart
des versions de fdisk
à n'avoir accès qu'à environ 8 Gio de leur disque
- une sérieuse limitation de nos jours.
Dans le texte ci-dessous, M représente la capacité totale du disque dur, et C,
H, S, le nombres de cylindres, de têtes et de secteurs par piste.
Il suffit de donner H, S si l'on voit C comme étant défini par M / (H*
S).
Par défaut, H=64 et S=32.
H=64, S=32.
H=64, S=32 à moins que C ne soit supérieur à 1024, auquel cas H=255, S=63, C =
min(1023, M/(H*
S)).
(Comme ça C est tronqué, et H*
S*
C n'est pas une approximation de la
capacité M du disque dur. Ceci va dérouter la plupart des versions de
fdisk
.) Le code de ppa.c
utilise M+1 à la place de M et dit qu'à
cause d'un bug dans sd.c
, M est plus petit de 1.
H=64 et S=32 à moins que C ne soit supérieur à 1024 ou que, encore mieux, l'option du BIOS `> 1 GB' ait été activée, auquel cas H=255 et S=63.
Demande au contrôleur lequel des deux schémas de conversion est utilisé, et se sert soit de H=255, S=63, soit de H=64, S=32. Dans le dernier cas, il y a un message au démarrage qui dit "aha1542.c: Using extended bios translation" ("aha1542.c: Utilisation du mode de conversion étendu du bios")
H=64 et S=32 à moins que C ne soit supérieur à 1024 ou que, mieux encore, le paramètre de démarrage "extended" ait été passé, ou que le bit `extended' ait été positionné dans la SEEPROM ou dans le BIOS, auquel cas H=255, S=63. Dans Linux 2.0.36 ce mode de conversion étendu devrait toujours être automatiquement utilisé si il n'y a pas de SEEPROM, mais dans Linux 2.2.6, si le même cas se présente, le mode de conversion étendu est utilisé seulement si l'utilisateur le demande au travers du paramètre de démarrage (de ce fait, quand une SEEPROM est trouvée, le paramètre de démarrage est ignoré). Cela signifie qu'une configuration qui fonctionne en 2.0.36 peut ne pas démarrer avec un noyau 2.2.6 (LILO nécessite alors le mot-clé `linear', ou le noyau a besoin du paramètre `aic7xxx=extended' au démarrage).
H=64 et S=32 à moins que C ne soit supérieur à 1024, ou que, encore mieux, le mode de conversion étendu ait été autorisé au niveau du contrôleur, auquel cas si M < 2^22 alors H=128, S=32 ; sinon H=255, S=63. Cependant, après avoir fait ce choix pour (C,H,S), la table des partitions est lue, et si pour l'une des trois possibilités (H,S) = (64,32), (128,32), (255,63) la valeur endH=H-1 est vue quelque part, alors cette paire est utilisée, et le message "Adopting Geometry from Partition Table" ("Adoption de la géométrie lue dans la table des partitions") est affiché au démarrage.
Il trouve l'information sur la géométrie dans la Table des Paramètres des
Disques du BIOS (BIOS Drive Parameter Table), ou lit la table des
partitions et utilise H=endH+1, S=endS pour la première partition, à
condition qu'elle ne soit pas vide, ou utilise H=64, S=32 pour M < 2^21
(1 Gio), H=128, S=63 pout M < 63*
2^17 (3.9 Gio) et H=255, S=63 dans
les autres cas.
Il utilise le premier couple (H,S) = (64,32), (64,63), (128,63), (255,63) qui rendra C < 1024. Dans le dernier cas, C est ramené à la valeur 1023.
Il lit C,H,S depuis le disque dur. (Horreur !) Si C ou S sont trop grands,
alors il fixe S=17, H=2 et double la valeur de H tant que C <= 1024. Cela
signifie que H sera mis à 0 si M > 128*
1024*
17 (1.1 Gio). C'est
un bug.
Un de ces trois couples de référence est utilisé ((H,S) = (16,63), (64,32), (64,63)) en fonction du mode de cartographie du contrôleur.
Regardez la table des partitions. Puisque par convention les partitions se
terminent à la limite d'un cylindre, nous pouvons, étant donné que end =
(endC,endH,endS)
pour n'importe quelle partition, simplement fixer H =
endH+1
et S = endS
. (Il est rappelé que le décompte des secteurs
commence à 1.)
Plus précisément, voilà ce qui est fait :
s'il existe une partition non vide, prendre la partition avec le plus grand
begin
. Pour cette partition, regarder endH+1
, calculé à la fois en
additionnant start
et length
, et en assumant le fait que cette
partition se termine à la limite d'un cylindre. Si les deux valeurs
concordent, ou si endC
= 1023 et start+length
est un multiple entier
de (endH+1)
, alors accepter le fait que cette partition se
termine effectivement sur la frontière d'un cylindre, et fixer H = *
endSendH+1
et S = endS
.
Si cela échoue, soit parce qu'il n'y a pas de partition, soit parce qu'elles ont
des tailles bizarres, il faut uniquement se fier à la capacité totale M
du disque dur.
Algorithme : fixer H = M/(62*
1024) (arrondi au chiffre supérieur),
S = M/(1024*
H) (arrondi au chiffre supérieur), C = M/(H*
S) (arrondi
au chiffre inférieur).
Ceci a pour effet de générer un triplet (C,H,S) avec C égal à 1024 au plus, et
S égal à 62 au plus.