LINUX.ORG.RU

Правка initrd файла

 ,


1

3

Необходимо изменить initrd файл так, чтобы в конечном итоге иное блочное устройство использовалось в качестве корневого. При этом используются системы с версиями ядра 2.4 и 2.6 :(

В системе с ядром 2.4 заключительная часть init-файла (linuxrc) образа initrd выглядит следующим образом:

...
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

В системе с ядром 2.6 иначе:

...
mkrootdev -t ext4 -o defaults,ro /devv/sda3
mount /sysroot
setuproot
switchroot

На данном этапе у меня возникает путаница, что именно делает каждая строка в обоих приведённых фрагментах. Подробному разъяснению этого момента я буду очень рад.

Кроме того, мне надо изменить файлы так, чтобы в качестве корневого монтировалось другое устройство, создаваемое в момент загрузки. А создаётся это устройство с помощью device-mapper-а. Не так важно, что именно делает получаемое устройство, но важно, что оно приводит реальное устройство в состояние «занято».

Так как иное устройство монтируется в качестве корневого, то я меняю (а в идеале удаляю) параметр root из конфигов загрузчиков (для LILO, например, вариант только удалить этот параметр, ибо LILO отказывается конфигурироваться, если устройство не существует).

Виртуальное устройство создаю так:

ld-linux.so.2 /bin/dmsetup create root_part /opt/bin/table

Устройство создаётся успешно по пути /dev/mapper/root_part

Подскажите, как изменить приведённые выше фрагменты. Спасибо!

что именно делает каждая строка в обоих приведённых фрагментах

Вы не знаете, что делает команда mount? Чё, правда?

В initrd для 2.4 всё команды есть в man'ах, читайте, в том числе и man nash, где описана команда mkrootdev. Так, можно сказать, что там все команды как-бы один syscall.

Для initrd для 2.6 команды хуже документированы, но можно смотреть исходники nash. ″mkrootdev″ создаёт записи в /etc/fstab для монтирования новой корневой ФС в /sysroot. initrd распакованный в ОЗУ позволяет создавать/редактировать файлы. ″setuproot″ монтирует каталоги /dev, /proc, /sys в /sysroot. ″switchroot″ удаляет всё из корня (старого корня), отмонтирует /dev, /proc, /sys, после чего делает непосредственно преключение корня — ″mount --move /sysroot /; chroot .″

mky ★★★★★ ()
Ответ на: комментарий от mky

Спасибо, за ответ!

Вы не знаете, что делает команда mount? Чё, правда?

Разумеется, знаю. Если в linuxrc файле дистрибутива с ядром 2.4 она выглядит стандартно, то в 2.6 у неё только один аргумент, и тот не устройство, а директория...

Ну, давайте тогда по порядку для 2.4.

man mkrootdev - нет такого. Но здесь написано, что он создаёт block inode (индексный дескриптор блочного устройства?) на устройство, которое должно монтироваться как root. То есть он типа создаёт ещё одно блочное устройство полностью «равное» реальному?

echo 0x0100 > /proc/sys/kernel/real-root-dev

В этот файл нужно записать номер блочного устройства, которое должно монтироваться как root. Вот только 0x0100 это dev/ram0... Что это значит?

mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot

Понятно. Монтирует то самое «равное» устройство в каталог /sysroot

pivot_root /sysroot /sysroot/initrd

На том же сайте написано, что она делает первый аргумент новой root-системой (как chroot чтоли? Или есть разница?), а старую root-систему переносит во второй аргумент.

umount /initrd/proc

Это зачем нужно?

И что происходит после этих всех команд? Очень хочется услышать здесь про файлы /etc/fstab и /sbin/init.

Спасибо!

AccumPlus ()
Ответ на: комментарий от AccumPlus

Есть подозрение, что для 2.6 это не shell скрипт, а nash скрипт. https://linux.die.net/man/8/nash

Из nash скрипта вообще нельзя ничего вызвать, только встроенные команды.

iliyap ★★★★ ()
Ответ на: комментарий от iliyap

Это в обоих случаях nash скрипт, причём этот тот nash, разработки RH специально для initrd скриптов, а не всякое прочее, что ещё гуглится.

Из nash можно вызвать любые внешние команды, у него даже PATH есть (/usr/bin, /bin, /sbin, /usr/sbin), но обычно обходятся встроенными в него командами.

В первых версиях nash как-то была тенденция делать встроенные команды на одно действие (один syscall), описывать их в man и давать имена как у обычных unix-команд, а потом понапридумывали всяких типа switchroot, которых в man'е нет и которые делают несколько действий.

mky ★★★★★ ()
Ответ на: комментарий от AccumPlus

После всех этих команд Nash exec-ает /sbin/init (или то, что указано в бутопции init=) с нового корня.

Вам надо добавить вызов dmsetup для сборки рутового девайса до mkrootdev.

iliyap ★★★★ ()
Ответ на: комментарий от AccumPlus

то в 2.6 у неё только один аргумент, и тот не устройство, а директория...

Ну, возможно, что в ″man nash″ про ″mount″ написано мало, но в ″man mount″ есть такой вариант вызова — тогда недостающая информация берётся из файла /etc/fstab.

mkrootdev совершенно разный для 2.4 и для 2.6. В initrd для 2.4 mkrootdev читает содержимое /proc/sys/kernel/real-root-dev и создаёт блочное устройство /dev/root с major/minor как прочитал в /proc. А в файле /proc/sys/... информация появляется от загрузчика ядра.«echo 0x0100 > /proc/sys/kernel/real-root-dev»

Далее, когда есть файл-устройство, уже можно сделать ″echo 0x0100″ так как в 2.4 initrd это ram-диск, именно ram-диск, а не tmpfs. В данном месте скрипта именно распакованный на ram-диск образ initrd является корневой файловой системой.

Потом монтируется настоящая корневая файловая система в /sysroot .

pivot_root это не chroot, это именно изменение корневой файловой системы на уровне ядра, а не для отдельного процесса. Первый аргумент становится новой корневой системой, а старая корневая файловая система монтируется во второй аргумент.

Потом из старой корневой файловой системы размонтируется proc-файловая система, она там больше не нужна. Точно не уверен, но по завершению скрипта initrd, ядро 2.4 попытается отмонтировать initrd и освободить память (очистить ram0), смотрированный там /proc помешает этому.

Файл /etc/fstab в initrd ядра 2.4, ЕМНИП не существовал, на основной корневой системе этот файл должен был содержать правильное описание корневой системы, чтобы после выполнения fsck, было прозведено перемонтирование корневой системы в rw. После завершения скрипта linuxrc в initrd, ядро само попытается найти на корневой системе /sbin/init и запустить его.

P.S. Для initrd для 2.6, nash другой и mkrootdev другой, он там смотрит командную строку ядра, понимате, если в ней root задан через LABEL. Главное, что он делает — записывает в /etc/fstab (который на initrd, а не на настоящей корневой ФС) строку, описывающую настояющую корневую ФС.

P.P.S. Надеюсь, что вы вобще прочитали man про fstab и знаете его формат и то, что с этим файлом взаимодействует команда mount.

mky ★★★★★ ()
Ответ на: комментарий от iliyap

И при этом mkrootdev вобще убрать из скрипта. В случае 2.4 нужно указать свой /dev/mapper/root_part в аргументах команды mount (ну и сделать /dev/root). В случае 2.6 нужно прописать /dev/mapper/root_part в fstab.

mky ★★★★★ ()
Ответ на: комментарий от mky

...и создаёт блочное устройство /dev/root с major/minor как прочитал в /proc

Под /proc вы имеете ввиду /proc/sys/kernel/real-root-dev?

Если да, то как видно в представленном участке кода, mkrootdev вызывается до помещения номера устройства в этот файл. Я проверил, перед вызовом mkrootdev этот файл содержит 0. На основе чего тогда создаётся /dev/root?

...именно распакованный на ram-диск образ initrd является корневой файловой системой
...Потом монтируется настоящая корневая файловая система в /sysroot .

Откуда же он знает, какая файловая система является настоящей? Мы до сих пор ни слова не сказали ему про /dev/sda3.

AccumPlus ()
Ответ на: комментарий от mky

В случае 2.4 нужно указать свой /dev/mapper/root_part в аргументах команды mount

Сделал так:

...
ld-linux.so.2 /bin/dmsetup create root_part /opt/bin/table
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/mapper/root_part /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

Работает. Ещё вариант так:

...
ld-linux.so.2 /bin/dmsetup create root_part /opt/bin/table
echo 0xFE00 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

Тоже работает. 0xFE00 - номер нового устройства. Какой вариант лучше? Если оба неверны, то скажите, в чём ошибка.

Конечно, код моего модуля для device-mapper-а не работет... Если у вас есть возможность, то можете глянуть? Ссылка. Спасибо!

...(ну и сделать /dev/root)

Как в моём втором варианте?

И при этом mkrootdev вобще убрать из скрипта
В случае 2.6 нужно прописать /dev/mapper/root_part в fstab.

Попробовал так:

...
mount /sysroot
setuproot
switchroot

И так:

...
mkrootdev -t ext4 -o defaults,ro /dev/mapper/root_part
mount /sysroot
setuproot
switchroot

Оба вызывают kernel panic. Фрагмент содержимого /etc/fstab (не знаю, как правильно оформлять обычный текст):

/dev/mapper/root_part    /    ext4    defaults    1 1
LABEL=/boot    /boot    ext4    defaults    1 2
...

Остальные строки неважны, я думаю. До изменения /etc/fstab первая строка начиналась на LABEL=/

AccumPlus ()
Ответ на: комментарий от iliyap

Спасибо за ответ!

После всех этих команд Nash exec-ает /sbin/init (или то, что указано в бутопции init=) с нового корня.

Понятно. То есть дальше надо смотреть его содержимое.

Вам надо добавить вызов dmsetup для сборки рутового девайса до mkrootdev.

Это тоже понятно. Не понятно как правильно указать новое устройство в качестве корневого. Хотя сейчас уже почти всё прояснилось (с ядром 2.4).

AccumPlus ()
Ответ на: комментарий от mky

Допустил ошибку в коде второго варианта. Вот верный код:

...
ld-linux.so.2 /bin/dmsetup create root_part /opt/bin/table
echo 0xFE00 > /proc/sys/kernel/real-root-dev
mkrootdev /dev/root
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
AccumPlus ()
Ответ на: комментарий от AccumPlus

Помещение чего-то в /proc/sys/kernel/real-root-dev не рекомендуется для ядер, которые умеют syscall pivot_root(). И, вроде как, последние ядра ветки 2.4 игнорировали запись в этот файл.

А в /proc/sys/kernel/real-root-dev содержится то, что положил туда загрузчик, или то, что было корневой ФС на момент компиляции ядра.

Я проверил, перед вызовом mkrootdev этот файл содержит 0.

Не знаю, как вы проверяли, 0 там на ядре 2.4 быть не может. При запуске lilo, /dev/sda3 превращаются в major/minor, на момент выполнения mkrootdev это число оказывается в /proc/sys/kernel/real-root-dev и он создаёт /dev/root с таким же major/minor, то есть фактически /dev/sda3.

ИМХО, первый вариант для 2.4 правильнее, только я бы вернул:

echo 0x0100 > /proc/sys/kernel/real-root-dev
перед ″mount″. Второй вариант опасен тем, что не факт, что какое-нибудь старое ядро из 2.4 не проигнорирует запись в /proc/sys/kernel/real-root-dev и не переключит в этот момент корневую ФС. А если вы уверены, что ваше устройство всегда будет ″0xFE00″, то вобще можно создать в образе initrd файл-устройство /dev/root с такими major/minor. И тогда в исходном скрипе нужно будет просто заменить ″mkrootdev″ на ″ld-linux.so.2 /bin/dmsetup ...″.

Что касается 2.6, то я вобще не понял, откуда у вас образ initramfs с существующим там файлом fstab? Какая версия mkinitrd?

P.S. Смотреть код модуля ядра пока нет времени.

P.P.S. Вы в курсе, то что при обновлении ядра (пакет) обычно вызывается mkinitrd и ваш рукотворный initrd будет затёрт? И вам по хорошему нужно изучать как правильно всунуть свой скрипт, чтобы он тоже вызывался при mkinitrd и корректировал автоматически создаваемый образ initrd

mky ★★★★★ ()
Ответ на: комментарий от mky

Не знаю, как вы проверяли, 0 там на ядре 2.4 быть не может. При запуске lilo, /dev/sda3 превращаются в major/minor, на момент выполнения mkrootdev это число оказывается в /proc/sys/kernel/real-root-dev ...

Да просто вывел содержимое. Дело в том, что LILO нужно переконфигурировать перед использованием нового initrd. Но конфигурация фэйлится, если я укажу в качестве root несуществующий раздел (/dev/mapper/root_part). Поэтому я в принципе убираю этот параметр. Думаю, что именно из-за этого этот файл и содержит 0.

Что касается 2.6, то я вобще не понял, откуда у вас образ initramfs с существующим там файлом fstab? Какая версия mkinitrd?

Я видимо вас не правильно понял. Файла там нет. Но ранее вы писали:

В случае 2.6 нужно прописать /dev/mapper/root_part в fstab

В какой именно fstab? На реальной корневой ФС или в initrd?

После mkrootdev файл fstab создаётся в initrd с содержимым:

/dev/root    /sysroot    ext4    defaults,ro    0 0

Интересно, на основе чего создаётся это устройство...

AccumPlus ()
Ответ на: комментарий от mky

А если вы уверены, что ваше устройство всегда будет ″0xFE00″, то вобще можно создать в образе initrd файл-устройство /dev/root с такими major/minor.

А как его создать?

И тогда в исходном скрипе нужно будет просто заменить ″mkrootdev″ на ″ld-linux.so.2 /bin/dmsetup ...″.

Типа такого?

...
ld-linux.so.2 /bin/dmsetup create root_part /opt/bin/table
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
AccumPlus ()
Ответ на: комментарий от AccumPlus

Да, писал, и речь там шла о том, что нужно убрать mkrootdev. А в предыдущем посте я писал про mkrootdev в 2.6:

Главное, что он делает — записывает в /etc/fstab (который на initrd, а не на настоящей корневой ФС)

Думаю, понятно, про какой fstab идёт речь. На настоящей корневой ФС скрипты из initrd ничего не делают.

Точно в 2.6 создаётся файл с содеримым:

/dev/root /sysroot ext4 defaults,ro 0 0

В первом посте была строка:

mkrootdev -t ext4 -o defaults,ro /devv/sda3

вроде как в fstab должен быть ″/dev/sda3″, а не ″/dev/root″.

mky ★★★★★ ()
Ответ на: комментарий от AccumPlus

Файл устройство создаётся командой mknod, как-то так:

cd dev
mknod root b 0xFE 0x00 

dev это каталог на образе initrd, на не на настоящей корневой ФС.

Где выполнять эту команду, зависит от того, как вы правите скрипт. Если у вас распакованный образ initrd, то выполнятей там, если вы правите скрипт mkinitrd, то вставьте этот mknod рядом с остальными mknod, которые делают устройства ″console″, ″null″, ″ram″.

Да, типа такого.

mky ★★★★★ ()
Ответ на: комментарий от mky

вроде как в fstab должен быть ″/dev/sda3″, а не ″/dev/root″.

Именно /dev/root. Но я сейчас сделал так:

ld-linux-x86-64.so.2 /bin/dmsetup create root_part /opt/bit/table
echo "/dev/mapper/root_part  /sysroot  ext4  defaults,ro  0 0" > /etc/fstab
mount /sysroot
setuproot
switchroot

При этом в реальном /etc/fstab нужно также поменять root раздел на новый:

/dev/mapper/root_part    /    ext4    defaults    1 1

Всё работает.

AccumPlus ()
Ответ на: комментарий от mky

Понял, спасибо. Всё же я думаю, что не могу быть уверен, что номер будет константным.

К слову, содержимое /proc/sys/kernel/real-root-dev действительно зависит от параметра root. Так как я его не передаю, то пишу туда сам руками. В конечном итоге получил следующее:

...
ld-linux-x86-64.so.2 /bin/dmsetup create root_part /opt/bit/table
# тут получаю номер созданного устройства
echo 0xFE00 > /proc/sys/kernel/real-root-dev
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

Работает. В общем, спасибо большое! Вопрос считаю решённым.

AccumPlus ()
Ответ на: комментарий от mky

Да, типа такого.

Вот только новое устройство создаётся в текущей корневой директории в каталоге /dev. После pivot_root это устройство оказывается в каталоге «старой» корневой системы. Как сделать так, чтобы оно было и в каталоге /dev нового корня?

Вопрос касается именно ядра 2.4. На 2.6 всё работает.

AccumPlus ()
Ответ на: комментарий от mky

Действительно, я поторопился с закрытием вопроса. Проблема с 2.4 ядром.

# Создаю своё устройство
ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table
# Записываю номер нового устройства
echo 0xFE00 > /proc/sys/kernel/real-root-dev
# Создаю /dev/root на основе моего устройства
mkrootdev /dev/root
# Не очень понимаю, зачем это
echo 0x0100 > /proc/sys/kernel/real-root-dev
# Монтирую /dev/root на /sysroot
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
# Помещаю текущую файловую систему в /sysroot/initrd, текущей делаю /sysroot
pivot_root /sysroot /sysroot/initrd
# Тут понятно
umount /initrd/proc

Что происходит с каталогом /dev? Моё устройство создаётся в каталоге /dev файловой системы initrd. Как это устройство попадёт в /dev реальной ФС?

После завершения linuxrc, init делает перемонтирование корневой файловой системы в соответствии с /etc/fstab. То есть там я должен указать своё новое устройство, что и делаю. Но оно отсутствует в каталоге /dev реальной файловой системы, отчего меня выбрасывает с ошибкой в терминал. Там я проверил, что у меня смонтировано, и обнаружил, что в качестве корневой системы используется /dev/hda3!!! Откуда он взял это?? В конфиге загрузчика я убрал параметр root, в linuxrc ни слова об этом разделе, в /etc/fstab тоже.

AccumPlus ()
Ответ на: комментарий от AccumPlus

обнаружил, что в качестве корневой системы используется /dev/hda3!!!

Информация из /proc/mounts ?

Все необходимые файлы-устройства должны быть в созданы /dev/ настоящей корневой системы заранее (на этапе установки ОС или модуля-драйвера).

Запись для корневой ФС в /etc/fstab настоящей корневой ФС должна быть, по ней происходит перемонтирование ro -> rw и появляется запись в /etc/mtab.

mky ★★★★★ ()
Ответ на: комментарий от mky

Информация из /proc/mounts ?

Ага. Ещё раз повторюсь, что я вываливаюсь в терминал, когда уже работает init. То есть я нахожусь в реальной корневой файловой системе.

Все необходимые файлы-устройства должны быть в созданы /dev/ настоящей корневой системы заранее

Это невозможно сделать заранее, так как нельзя создать виртуальное устройство на уже примонтированное (на root раздел). Единственный выход - создать его в initrd. И здесь опять же, я вынужден создавать его в /dev директории initrd. Я думаю, что основная проблема кроется в этом хитром использовании /dev/hda3 раздела в качестве корневого. Понять бы, где это указывается, и указать мой раздел вместо него.

AccumPlus ()
Ответ на: комментарий от AccumPlus

так как нельзя создать виртуальное устройство на уже примонтированное (на root раздел).

Это ещё почему? Пакеты туда устанавливать можно, а файлы создавать нельзя?

mky ★★★★★ ()
Ответ на: комментарий от mky

При попытке вызвать dmsetup на уже примонтированное устройство device mapper ругается на то, что устройство занято.

AccumPlus ()
Ответ на: комментарий от AccumPlus

Зачем вам нужен dmsetup? Вы концепцию файл-устройство знаете? При обращении к такому файлу запрос будет автоматически идти к драйверу в ядре по major'у файла-устройства. ″mknod″ вам в руки.

mky ★★★★★ ()
Ответ на: комментарий от mky

Мне нужно именно создать некий транслятор запросов. Драйвер должен быть свой (вы это могли видеть в смежной теме). В будущем планируется добавлять обработку запросов... Переадресовывать, шифровать и так далее.

Я нашёл только способ создания некого маппирующего устройства на реальное с помощью device-mapper-а.

Если есть другой способ, то хочу услышать, ибо линукс для меня был более-или-менее известен только на уровне пользователя (максимум продвинутого). Всех его особенностей я не знаю, увы.

В то же время, пока что стоит именно такая задача. Так что если есть идеи по поводу работы initrd (почему там монтируется /dev/hda3, а не моё устройство), то излагайте. Даже лучше, если сначала будет решён этот вопрос.

Спасибо!

AccumPlus ()
Ответ на: комментарий от mky

К слову, я чуть ошибся.

В следующем коде рутом становится не /dev/hda3, а /dev/root:

ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table
echo 0xFE00 > /proc/sys/kernel/real-root-dev
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

Вроде бы так и должно быть. Но в /etc/fstab я не могу указать своё устройство, потому что оно отсутствует в /dev директории (оно находится в /dev директории initrd).

Если удалить строку:

echo 0x0100 > /proc/sys/kernel/real-root-dev

то во время работы init выводится сообщение, что /initrd занято, и его невозможно отмонтировать.

А вот если делаю так:

ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/mapper/root_part /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

то есть напрямую монтирую своё устройство, то после падения init /proc/mounts показывает /dev/hda3 в качестве корневого раздела. Для меня это действительно странно.

AccumPlus ()
Ответ на: комментарий от AccumPlus

Мы сейчас опять пойдём по кругу, потому что вы не хотите читать ″man mknod″.

потому что оно отсутствует в /dev директории (оно находится в /dev директории initrd).

Устройство может находится где угодно, где указали mknod, там и будет создан файл-устройство и их может быть сколько угодно в системе. Если у вас всегда ″0xFE00″, то создайте /dev/mapper/root_part на настоящей корневой системе с этими major/minor. Если нет, и эти числа различаются от запуска к запуску, то придётся тащить busybox в initrd, чтобы там появилась команда mknod...

Что касается поведения ядра 2.4 относительно монтирования корневой ФС при initrd, то оно запутаное и немного отличается от версии к версии. У ядра всегда есть заданная при компиляции корневая ФС (смотрится командой rdev на несжатый образ ядра). Загрузчик может туда записать другое устройство. Изначально после завершения скрипта в initrd ядро само монтировало себе вышеописанную корневую ФС. Потом добавили /proc/sys/kernel/real-root-dev и стала возможна запись в этот файл из initrd, а ядро при завершении initrd монтировало то, что туда записали. И сделали хак, что если туда записать 0x0100 = /dev/ram0 = initrd, то ядро не будет перемонтировать корневую ФС при завершении initrd, а просто запустит /sbin/init. А потом добавили pivot_root (syscall и команду) и сказали, что надо пользоваться им, и что initrd скрипт должен монтировать корневую ФС, а ядро не должно.

Какой механизм срабатывает в вашем случае сказать сложно. В любом случае у вас должно быть устройство 0xFE00 в /dev/ на основной ФС, иначе вам не перемонтировать ФС из ro в rw.

Ещё покажите содержимое ″/sysroot/initrd/proc/mounts″ и ″/sysroot/initrd/proc/partitions″ сразу после выполнения ″pivot_root″ в initrd.

mky ★★★★★ ()
Ответ на: комментарий от mky

В любом случае у вас должно быть устройство 0xFE00 в /dev/ на основной ФС, иначе вам не перемонтировать ФС из ro в rw.

Но в случае с ядром 2.6 это условие оказывается необязательным. В реальной ФС этого устройства нет, и оно создается так же в ФС initrd. Однако потом чудесным образом оказывается в реальной. Возможно, это особенности setuproot и switchroot...

Выполняя вот этот код:

ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table
echo 0xFE00 > /proc/sys/kernel/real-root-dev
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

содержимое /sysroot/initrd/proc/mounts после pivot_root (очевидно, что я делаю 'cat /initrd/proc/mounts'):



rootfs / rootfs rw 0 0
/dev/root.old /initrd ext2 rw 0 0
/proc /initrd/proc proc rw 0 0
/dev/root / ext3 ro 0 0

и содержимое /sysroot/initrd/proc/partitions:

major minor #blocks  name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq
3     0     33554432 hda  72  192    1922  10   2   0      16    0    0       10  10
3     1     104391   hda1 0   0      0     0    0   0      0     0    0       0   0
3     2     2040255  hda2 0   0      0     0    0   0      0     0    0       0   0
3     3     31407075 hda3 66  170    1882  10   2   0      16    0    0       10  10

Выполняя такой код:

ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/mapper/root_part /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

содержимое /sysroot/initrd/proc/mounts:

rootfs / rootfs rw 0 0
/dev/root.old /initrd ext2 rw 0 0
/proc /initrd/proc proc rw 0 0
/dev/mapper/root_part / ext3 ro 0 0

и содержимое /sysroot/initrd/proc/partitions:

major minor #blocks  name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq
3     0     33554432 hda  72  192    1922  10   2   0      16    0    0       10  10
3     1     104391   hda1 0   0      0     0    0   0      0     0    0       0   0
3     2     2040255  hda2 0   0      0     0    0   0      0     0    0       0   0
3     3     31407075 hda3 66  170    1882  10   2   0      16    0    0       10  10
AccumPlus ()
Ответ на: комментарий от AccumPlus

В случае с ядром 2.6 вобщё всё по другому. /dev практически сразу это отдельная ФС (tmpfs), и всё что там насоздаётся, сохраняется в ней, а setuproot перемонтирует её к настоящему корню.

В 2.4 был отдельный тип файловой системы для файлов-устройств (devfs), но, она была не особо удобена/популярна. Если и использовалась, то только на настоящей корневой системе, из initrd-скрипта не создавалась. ЕМНИП, проблема была в том, что если ты один раз смонтировал devfs куда-то, то потом уже нельзя отмонтировать. То есть, если смонтировал в /dev в initrd, то она окажется в /initrd/dev и не отмонтируется, следовательно, не отмонтируется /initrd и не освободится ОЗУ.

Ваш /proc/partitions меня удивил. По логике, там должны быть перечислены все блочные устройства в системе, но вашего /dev/mapper/root_part нет. Возможно, что это нормально для 2.4.x, потому что там не появляется и /dev/loop0, до некоторой степени аналог вашему устройству. Надо ещё подумать.

mky ★★★★★ ()
Ответ на: комментарий от mky

Ваш /proc/partitions меня удивил

Так то и в моей текущей системе (4.9.11-1) /dev/loopX отсутствуют в /proc/partitions, хотя в каталоге /dev они есть.

Я думаю, вы знаете, но на всякий случай скажу, что я выводил содержимое /proc/partitions в initrd ФС. Сразу после pivot_root в реальной файловой системе каталог /proc пустой.

И device mapper на моей системе немного иначе работает. Он создаёт устройство /dev/dm-0 и ссылку на него в /dev/mapper с именем, которое я указываю dmsetup утилите. Я проверил, на 2.4 он не создаёт никаких ссылок, чисто устройство в /dev/mapper.

Может быть, эта информация чем-то поможет.

P.S. Вы можете мне посоветовать какую-нибудь книгу, в которой бы описывались особенности устройства этого уровня Linux-систем? Спасибо!

AccumPlus ()
Ответ на: комментарий от AccumPlus

У меня /dev/loopX появляются в /proc/partitions после того, как с ним будет связан файл (losetup или mount -o loop).

Cразу после pivot_root в реальной файловой системе каталог /proc пустой.

Да, так и должно быть, /proc монтирует init-скрипт реальной корневой ФС.

Книжку я вам не посоветую, вобще DM для 2.4 был на уровне патча, причём как-бы экспериментального/второстепенного, основной упор был на 2.5 и 2.6. Я не помню, использовался ли он кем-то для чего-то полезного. Запросто, что в 2.4 заложены какие ограничения на устройства /dev/mapper, но наверное сейчас об этом уже никто не вспомнит, даже разработчики, уже больше 10 лет прошло.

Попробуйте в версии initrd, в которой вы монтируете ″/dev/mapper/root_part″, убрать отмонтирование /initrd/proc, тогда ядро не должно отмонтировать /initrd. На основной корневой ФС сделайте символьную ссылку /dev/mapper/root_part -> /initrd/dev/mapper/root_part. Сылку можно создавать и на несуществующий файл. Может в таком варианте взлетит...

mky ★★★★★ ()
Ответ на: комментарий от mky

Может в таком варианте взлетит...

Взлетело) Спасибо! При таком раскладе мой initrd будет всегда в оперативной памяти, верно?

AccumPlus ()
Ответ на: комментарий от AccumPlus

Да, причём он будет занимать фиксированный объём ОЗУ и, ЕМНИП, только ОЗУ, в swap не уйдёт, файлы на initrd удалять бесполезно, это ramdisk, а не tmpfs.

Можете продолжить в этом направлении, на initrd положить пустой образ маленькой ext2 в файле, там его копировать на /dev/ram1 (заранее создав нужный inode), потом монтировать его в /dev/mapper на initrd, а потом перемонтировать /dev/ram1 в /dev/mapper основной fs. Как-бы аналог /dev в 2.6.

mky ★★★★★ ()
Ответ на: комментарий от mky

Заранее прошу прощения за тупость)

там его копировать на /dev/ram1 (заранее создав нужный inode)

Я так понимаю, мне нужно, чтобы /dev/ram1 стал типа моим образом ext2, который будет потом монтироваться в /dev/mapper... Вот только я пока не могу понять, что для этого нужно сделать)

Заранее создал inode /dev/ram1 на initrd и там же создал маленький образ ext2. Как в момент загрузки закинуть свой образ в устройство?

AccumPlus ()
Ответ на: комментарий от mky

Пока сделал так.

В загруженной системе добавляю устройство:

cd dev
mknod ram1 b 0x01 0x01

Создаю образ ext2 (методом тыка дошёл, что минимально возможный размер приблизительно 60КБ):

cd etc
dd if=/dev/zero of=mapper_dir bs=1024 count=60
mkfs.ext2 mapper_dir

И код linuxrc:

ld-linux.so.2 /bin/dd if=/etc/mapper_dir of=/dev/ram1 bs=1024 count=60
mount -t ext2 /dev/ram1 /dev/mapper
ld-linux.so.2 /bin/dmsetup create root_part /opt/bit/table

echo 0xFE00 > /proc/sys/kernel/real-root-dev
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o acl,nosecdel,secrm --ro -t ext3 /dev/root /sysroot
umount /dev/mapper
mount -t ext2 /dev/ram1 /sysroot/dev/mapper
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc

Код работает. Но есть вопросы.

1. Почему я сразу не могу залить мой образ в /dev/ram1? (как бы для меня это не выглядело странным, но это действительно не работает)

2. Если ram1 - просто файл в каталоге /dev моего initrd, то почему, размонтировав initrd, я всё ещё могу работать с точкой монтирования этого устройства? В данном случае, почему /dev/mapper всё ещё доступно, если устройство ram1 лежит на отмонтированном устройстве initrd?

AccumPlus ()
Ответ на: комментарий от AccumPlus

У вас какой-то серьёзный пробел в понимании, что за файлы лежат в /dev/. То, что там лежит, с точке зрения файловой системы — это имя файла, указывающее на инод. Больше на файловой системе для файла-устройства ничего нет. В иноде выставлен флаг, что это блочное устройство и определены major и minor.

И файл-устройство может быть в любом каталоге файловой системы.

Когда в парметрах системному вызову (ядру) даётся файловый дискриптор, указывающий на файл-устройство, ядро смотрит какой там major/minor и вызывает соответствующий драйвер, который уже лезет в память или к диску или ещё как. Как правило, major определяет драйвер, а minor уже внутри драйвера обрабатывается.

Когда вы что-то пишете в /dev/ram1, то на самом деле это что-то передаётся драйвер ram-диска (если он есть в ядре), и он складывает это что-то в отдельную область ОЗУ (на ram-диск 1). При этом эти данные остаются там, не важно, есть ли файл /dev/ram1 или его уже удалили. При этом драйвер даже не знает, как называется на файловой системе файл-устройство, обращение к которому привело к вызову этого драйвера, только major/minor.

Не важно, сделаете вы ″mknod /dev/ram1 b 0x01 0x01″ или ″mknod /tmp/ramram1 b 0x01 0x01″, оба файла будут «указывать» на один ram-диск. И, для того, чтобы выполнить команду ″mknod″ совсем не обязательно, чтобы в ядре был драйвер соответствующего устройства, ядро ищет нужный драйвер только при обращении к этому файлу, а не при его создании.

Если что-то не понятно, попробуйте погуглить про файлы-устройства, я особо подробнее объяснить не смогу, а в какой книжке я про это читал уже и не вспомню. И это так во всех Юниксах, не только в Линуксе.

P.S. Надеюсь, сейчас никто не набежит с заявлениями, что обычно /tmp монтируют с флагом ″nodev″ и там не будет работать ram-диск.

mky ★★★★★ ()
Ответ на: комментарий от mky

У вас какой-то серьёзный пробел в понимании, что за файлы лежат в /dev/

Да и не только в этом.. Но знаний поприбавилось - это точно)

Спасибо большое! Вы очень мне помогли! Код то мой примерно отражает то, что вы мне хотели донести?

AccumPlus ()
Ответ на: комментарий от AccumPlus

По коду не знаю, если работат, то и ладно.

Я советовал не создовать /dev/root, а сразу монтировать:

mount -o acl,nosecdel,secrm --ro -t ext3 /dev/mapper/root_part /sysroot
тогда как бы логично, что /dev/mapper отдельнай ФС и мы её и сохраняем при переходе от initrd к настоящей корневой ФС.

Ну и

ld-linux.so.2 /bin/dd if=/etc/mapper_dir of=/dev/ram1 bs=1024 count=60
здесь ″bs=1024 count=60″ явно лишнее, по умолчанию dd копирует весь файл до конца. Так, как бы ошибки нет, но эти аргументы вносят путаницу в понимание скрипта, возникает мысль, что раз указан объём копируемых данных, то /etc/mapper_dir это не просто файл с образом ФС, а ещё что-то.

mky ★★★★★ ()
Ответ на: комментарий от mky

здесь ″bs=1024 count=60″ явно лишнее, по умолчанию dd копирует весь файл до конца.

И конец будет определяться конфигурацией ядра ramsize. Так что явно не лишнее.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

if=/etc/mapper_dir , больше чем этот файл не скопирует.

Про какой ramsize идёт речь непонятно. Если это параметр ядра, то он уже в 2.0.0 считался устаревшим, а максимальный размер динамически выделяемого RAD-диска задавался ″ramdisk_size″ и не превышал 16 Мбайт.

mky ★★★★★ ()
Ответ на: комментарий от mky

if=/etc/mapper_dir , больше чем этот файл не скопирует.

Да, но это не помешает, так как до этого идёт if=/dev/zero и mkfs можно тоже ограничивать. Для симметричности. А для красоты ещё и в виде переменных вынести.

максимальный размер динамически выделяемого RAD-диска задавался ″ramdisk_size″ и не превышал 16 Мбайт.

Об этом и речь, редко когда надо такой большой ramdisk.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

dd if=/dev/zero of=mapper_dir bs=1024 count=60

Это совсем не перед этим, можно сказать, это в другом пространстве, здесь count нужен и задаёт размер. С помощью этого dd делается файл под образ ФС. По идее, это делается один раз, и записывается в initrd.

А там, когда ″dd if=/etc/mapper_dev″, как раз и может быть потенциальная проблема, если образ ФС станет не 60 кбайт. Допустим, когда-нибудь ТС понадобится эта ФС большего размера, он её образ переделает, а в linuxrc забудет изменить ″count=60″.

mky ★★★★★ ()
Ответ на: комментарий от mky

Потому и предлагал сделать переменной. Она то будет одинаковой для if, of и mkfs. Чем хорош dd, так тем, что можно bs сказать большой. А count будет для симметричности.

vodz ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.