Драйвер IDE имеет пять источников информации о геометрии. Первый (G_user) указывается пользователем в командной строке. Второй (G_bios) - это таблица с фиксированными параметрами диска в BIOS (только для первого и второго дисков),которая считывается при запуске, до переключения в 32битный режим. Третий (G_phys) и четвертый (G_log) - возвращаются IDE контроллером, в ответ на команду IDENTIFY,это 'физическая' и 'текущая логическая' геометрии.
С другой стороны драйверу нужны две величины для определения геометрии
- это G_fdisk,возвращаемая HDIO_GETGEO
ioctl,
и G_used,которая непосредственно используется при операциях
ввода вывода.Оба этих параметра инициализируются для G_user если
таковой указан,или для G_bios,когда информация предоставлена в CMOS,
и G_phys в любом другом случае. Если использование G_log выглядит
разумным,то G_used устанавливается для него. В случае же если
G_phys выглядит оптимальным, то G_used устанавливается для G_phys.
Примечание: термин 'выглядит оптимальным,разумным' - означает, что число
головок лежит в пределах 1-16.
Говоря проще : параметры переданные в командной строке имеют
больший приоритет, чем параметры полученные от BIOS,и будут определять
геометрию которую видит fdisk
,но если будет указана преобразованная
геометрия (более 16 головок),то при операциях ввода/вывода она
будет замещена геометрией полученной от команды IDENTIFY.
Заметит что G_bios достаточно ненадежен: для систем загружающихся с SCSI первый и второй диски, могут быть SCSI дисками,и геометрия которую BIOS сообщает для sda будет использована ядром для hda. Более того,диски которые не упомянуты в BIOS Setup,не будут видны BIOS. Это означает, что например на IDE системе,где hdb не упомянут в Setup, геометрия сообщаемая BIOS для первого и второго дисков, будет геометрий hda и hdc.
Ситуация с SCSI немного отличается,т.к. все SCSI команды используют
логические номера блоков(секторов),поэтому геометрия не зависит
от физических процессов ввода/вывода.
В тоже время формат таблицы разделов такой же что и для IDE,
поэтому fdisk
'у приходиться изобретать некую геометрию,он
также использует HDIO_GETGEO
. Несмотря на это fdisk
различает SCSI и IDE диски.
Как можно видеть из описанного выше, различные драйвера изобретают
различную геометрию. Что вызывает некий беспорядок и неорганизованность.
Если вы не используете DOS или ему подобные системы, то надо опасаться любых установок, связанных с расширенным преобразованием,просто используйте 64 головки,32 сектора на дорожку(для того чтобы у вас на 1 цилиндр приходился 1 МиБ),если это возможно,так чтобы при перестановки диска с одного контроллера на другой не возникало проблем. Некоторые (aha152x, pas16, ppa, qlogicfas, qlogicisp) драйвера SCSI дисков, так обеспокоены совместимостью с DOS ,что они не позволят Линукс использовать более 8 ГиБ. Это баг.
Что такое настоящая геометрия?
Самый простой ответ - таковой не существует.
Даже если таковая и была бы , вам не нужно бы было её знать
и не в коем случае не рассказывать о ней fdisk
или LILO или ядру.
Это дело только SCSI контроллера и диска.
Но если вам это жизненно необходимо, вы можете спросить сам диск.
Существует очень важная команда READ CAPACITY, которая сообщает
полный размер диска, и команда MODE SENSE, которая на странице
Rigid Disk Drive Geometry (страница 04) сообщает количество
цилиндров и головок (т.е. параметры которые нельзя изменить),
на странице Format (страница 03) дает количество байт в секторе
и количество секторов на дорожку.
Последнее число обычно зависит от notch, а количество секторов на
дорожку обычно переменное - внешние треки имеют больше секторов,чем внутренние.
Программа scsiinfo
сообщает подобную информацию.
Существует огромное количество деталей,которые никто,включая операционную
систему,знать не хочет.
Более того , т.к. мы концентрируемся на fdisk
и LILO,
то обычно получаемые величины вроде C/H/S=4476/27/171 -
значения которые не могут быть использованы fdisk
,
т.к. в таблице разделов эти значения не помещаются в отведенные
им поля.
А откуда-же берет данную информацию HDIO_GETGEO
?
Оно опрашивает SCSI контроллер,или делает сложный запрос.
Некоторые драйвера думают что мы хотим знать настоящие значения,
хотя на самом деле нам нужно знать лишь то, что будет
использовать Fdisk в DOS или OS/2.
Заметит что fdisk
для Линукс требуются H и S - количество
головок и секторов на дорожку, для преобразования LBA номеров
в c/h/s адреса,но значение C (количество цилиндров) не играет
роли в данном преобразовании.
Некоторые драйвера используют значения C/H/S = 1023/255/63 чтобы
сигнализировать, что емкость диска как минимум 1023*
255*
63
секторов.Это плохо,т.к. не соотвествует реальным размерам, и ограничит
пространство доступное пользователям большинства версий
fdisk
8'ю ГиБ'ами.Это наиболее серьезная проблема сегодня.
В описании данном выше, M обозначает общую емкость диска,
и C/H/S количество цилиндров,головок и секторов/дорожка.
Задание H,S необходимо если мы расчитываем C как M/(H*
S).
По умолчанию, H=64, S=32.
H=64, S=32.
H=64, S=32 если C не > 1024,
в таком случае
H=255, S=63, C = min(1023, M/(H*
S)).
(Поэтому C урезается, и H*
S*
C не является
усредненным значение емкости диска.
Это вызывает недоумение у большинства версий fdisk
.)
Код ppa.c
использует M+1 вместо M и сообщает что из за бага
в sd.c
M уменьшено на единицу.
H=64, S=32 если C не > 1024 и `> 1 GB' опция в BIOS включена, в этом случае H=255, S=63.
Спрашивает контроллер какая из двух возможных схем преобразования используется,и использует либо H=255, S=63 либо H=64, S=32. В общем случае появляется следующее сообщение при загрузке. "aha1542.c: Использует расширенное преобразование BIOS".
H=64, S=32 если C не > 1024, и загрузочный параметр "extended" либо бит "extended" был установлен в SEEPROM или BIOS, в это случае H=255, S=63. В Линукс 2.0.36 расширенное преобразование всегда устанавливалось ,если не было найдено SEEPROM,но в Линукс 2.2.6 если SEEPROM не найден то расширенное преобразование устанавливается только если пользователь задал соответствующий загрузочный параметр. (если SEEPROM найден то загрузочный параметр игнорируется). Это значит, что setup,который работает с 2.0.36 может перестать загружаться с 2.2.6(и требовать указания параметра 'linear' для LILO,или параметра ядра `aic7xxx=extended' )
H=64, S=32 если C не >= 1024, и дополнительно,расширенное преобразование не было включено на контроллере ,в этом случае: если M < 2^22 то H=128, S=32; иначе H=255, S=63. Однако после выбора значений для C/H/S,считывается таблица разделов, и если для одной из трех возможностей (H,S) = (64,32), (128,32), (255,63) или значение H=H-1 найдено где либо,то используется пара (H,S),и выдается загрузочное сообщение "Adopting Geometry from Partition Table".
Находит информацию о геометрии в таблице параметров диска BIOS,
или считывает таблицу разделов и использует H=endH+1, S=endS
для первого раздела (если такая информация дана), или использует
H=64, S=32 для M < 2^21 (1 ГиБ),
H=128, S=63 для M < 63*
2^17 (3.9 ГиБ) и H=255, S=63 иначе.
Использует первое из (H,S) = (64,32), (64,63), (128,63), (255,63) которое сделает C равным < = 1024. В последнем случае, усекает C до 1023.
Считывает C,H,S с дичка. (Кошмар!) Если C или S слишком велики, то
устанавливает S=17, H=2 и удваивает H до тех пор пока C не станет <= 1024.
Это означает,что H будет установлено в 0 если M > 128*
1024*
17 (1.1 ГиБ).
Это баг.
Одна из трех разметок ((H,S) = (16,63), (64,32), (64,63)) используется в зависимости от режима разметки контроллера.
Взглянем на таблицу разделов. Т.к. обычно разделы оканчиваются
на границе цилиндров, мы можем задать end = (endC,endH,endS)
для любого раздела , просто укажите H = endH+1
и S = endS
.
(обратно сектора отсчитываются от 1.)
Если быть более точными , делается следующее.
Если есть не пустой раздел , выбирается раздел с наибольшим beginC
.
Для этого раздела , смотрим на end+1
, вычисляемое
путем добавления start
и length
и предполагая
что раздел заканчивается на границе цилиндров.
Если оба значения совпадают, или если endC
= 1023 и start+length
целое произведение (endH+1)
,
то предполагается что данный раздел расположен на границе цилиндров.
, и используется H = *
endSendH+1
и S = endS
.
Если это не срабатывает, потому - что нет разделов , или потому - что
они имеют странные размеры, то используется только M - емкость диска.
Алгоритм: возьмем H = M/(62*
1024) (округленное вверх), S = M/(1024*
H)
(округленное вверх), C = M/(H*
S) (округленное вниз).
Это имеет эффект умножения (C,H,S) с C максимум 1024
и S максимум 62.