LINUX.ORG.RU

какое решение есть у mkinitcpio для *медленных* btrfs-multiple-devices?

 , ,


0

1

добрый день!

этот вопрос я долго пытался гуглить и читать на archwiki — но ответ так и не нашёл..

вопрос для меня — сейчас сугубо теоретический. так как на практике у меня пока-что нет ещё *медленных* накопителей, на которых я мог бы поэкспериментировать с btrfs-multiple-devices и mkinitcpio :) ..

итак вопрос: какое решение есть у mkinitcpio для *медленных* btrfs-multiple-devices?

(медленный мультидисковый btrfs — в качестве корня Арчика).

сразу предостерегу что hook «btrfs» ( /usr/lib/initcpio/hooks/btrfs из пакета btrfs-progs) — делает всего лишь только операцию btrfs device scan и больше ни чего..

########## в чём я вижу возможную проблему? ##########

проблема в том как именно заставить mkinitcpio *ожидать* момента когда обнаружатся *все-все-все* устройства необходимые для монтирования *мультидискового* btrfs..

ещё раз повторяю, что обсуждаю тут — ту ситуацию которую сам не могу проверить.. диванный теоретик короче :-) ..

всем другим отписавшимся диванным теоретикам — заранее выражаю благодарность.. и НЕтеоретикам — тоже :)

##########
# P.S. знаю что mkinitcpio позволяет легко писать собственные хуки (hooks), ...но хотелось бы узнать стандарное решение, без создания велосипедов :)


########## UPDATED ##########

решение проблемы:

использовать systemd в initramfs (вместо bash-скрипта):

какое решение есть у mkinitcpio для *медленных* btrfs-multiple-devices? (комментарий)

★★★★★

Последнее исправление: user_id_68054 (всего исправлений: 8)

А как происходит обнаружение таких мультидисковых томов на реальной системе? Тоже требуется руками выполнять btrfs device scan или тома детектятся сами через udev (как реакция на событие добавления в систему нового блочного устройства)?

Если второе, то systemd в помощь: надо пересоздать initcpio с использованием systemd и с включением нужных udev-правил. Тогда systemd будет ждать окончательного появления тома с нужной меткой/идентификатором.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

А как происходит обнаружение таких мультидисковых томов на реальной системе?

в уже загруженной системе — операцию btrfs device scan выполнять необходимости нет. как я понимаю scan нужен только если нет udev.

(как известно — mkinitcpio тоже имеет внутри себя udev..)

но в контексте вопроса моей темы — я не очень понимаю один момент «может ли ядро передать управление initramfs-скрипту — ещё до момента как определило все накопительные устройства? или передаст управление initramfs-скрипту — только ПОСЛЕ того как прочухала все накопительные устройства?»

а ещё замечу что все-все-все тома мультидискового btrfs — имеют один и тот же UUID.

то есть каталог /dev/disk/by-uuid/ — содержит ссылку только на одну (случайну) часть от мультидискового-btrfs

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 3)
Ответ на: комментарий от user_id_68054

initramfs-скрипт — это что вообще?

В initramfs есть свой init. В контексте арча это либо скрипт на баше, либо systemd. Он запускается самым первым, а всё остальное — уже забота самого init'а, ядро дальше ни при чём. Соответственно, инит должен стартануть udev, просканить устройства, дождаться их обработки udev'ом, дождаться появления блочного устройства с корневой ФС, примонтировать его и сделать pivot_root.

Поэтому весь вопрос в том, есть ли там udev, есть ли там нужные правила для udev'а и умеет ли инит ждать появления устройств.

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

ещё замечу что все-все-все тома мультидискового btrfs — имеют один и тот же UUID.

И как тогда монтировать результирующий том?

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

initramfs-скрипт — это что вообще?

В initramfs есть свой init. В контексте арча это либо скрипт на баше, либо systemd.

да, я как раз про этот «свой init» :-) .. на bash в моём понимании.. (про подвиги о том как засовывают systemd вместо bash в initramfs — только я на лор читал :))

внутри этого init — есть bash-функция poll_device():

poll_device() {
    local device=$1 seconds=${2//[!0-9]}

    [ "${seconds:-x}" = x ] && seconds=10
    deciseconds=$(( seconds * 10 ))

    # tenths of a second
    sleepinterval=1

    [ -b "$device" ] && return 0

    if [ "$udevd_running" -eq 1 ]; then
        msg "Waiting $seconds seconds for device $device ..." >&2
        while [ ! -b "$device" -a "$deciseconds" -gt 0 ]; do
            if [ "$sleepinterval" -ge 10 ]; then
                sleep 1
                deciseconds=$(( deciseconds - 10 ))
            else
                sleep .$sleepinterval
                deciseconds=$(( deciseconds - sleepinterval ))
                sleepinterval=$(( sleepinterval * 2 ))
            fi
        done
    fi

    [ -b "$device" ]
}

эта функция poll_device() — вызывается постоянно на каждый чих.. так что в обычном случае происходит ожидание.. это касается медленных накопителей, и всяких там mdadm (хотя для mdadm там есть и конкурентный более умный хук с использование udev-правил, вместо poll_device())

отдельных udev-правил для мультидисковых-btrfs — нет. при чём нет ни в initramfs ни в обычной загруженной системе... (но хм.. я тогда слегка запутался.. почему оно так зависит от udev?)

вобщем надо копать в сторону udev.. смотреть как оно в initramfs стартует — правильно?

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 3)
Ответ на: комментарий от intelfx

> ещё замечу что все-все-все тома мультидискового btrfs — имеют один и тот же UUID.

И как тогда монтировать результирующий том?

в уже загруженной системе:

mount /dev/disk/by-uuid/blahblahblah /mnt

то есть достаточно в команде указать любую часть (хоть первую, хоть вторую, хоть третью) от мультидискового устройства. а другую часть, видемо btrfs-модуль как-то сам узнаёт.. %) %)

если всех нужных частей в системе в даный момент — то mount выдаёт ошибку.

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от user_id_68054

Я почитал тут про этот btrfs в плане мультидисковых томов. ИМХО, наркомания какая-то: нужно воткнуть все устройства, сделать b-d-s и только потом монтировать том, указывая любое из принадлежащих ему устройств.

В общем, не знаю, как можно сделать это в initramfs в автоматическом режиме. С lvm всё куда лучше, на мой взгляд: там создание результирующего виртуального раздела инициируется из udev.

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

Поэтому весь вопрос в том, есть ли там udev, есть ли там нужные правила для udev'а и умеет ли инит ждать появления устройств.

вот как сратрует udev (в mkinitcpio`шном initramfs) :

run_earlyhook() {
    kmod static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
    systemd-tmpfiles --prefix=/dev --create
    /usr/lib/systemd/systemd-udevd --daemon --resolve-names=never
    udevd_running=1
}

run_hook() {
    msg ":: Triggering uevents..."
    udevadm trigger --action=add --type=subsystems
    udevadm trigger --action=add --type=devices
    udevadm settle
}

run_earlyhook() и run_hook() можно сказать одна функция за другой выполняются (между ними какие-то там фигня — и ничего особо важного не запускается).

можешь пожалуйста рассказать — после запуска таким образом udevd (как я написал в этом сообщении) — ведь НЕ происходит ни какого ожидания появления накопительных устройств в /dev/ ? верно?

то есть только умышленный запуск функции poll_device() (код которой написан выше) может ожидать и больше ни чего другого?

или же я *ошибаюсь* и на самом деле — udevd *синхронно-ждёт* появления в /dev/ всех-всех-всех накопительных устройств , и только после этого уходит в fork() ?

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 4)
Ответ на: комментарий от intelfx

В общем, не знаю, как можно сделать это в initramfs в автоматическом режиме.

как это сделать в initramfs в автоматическом режиме(?)..

ды очень просто... :-) достаточно лишь в initramfs-скрипте указать команды (перед монтированием):

poll_device /dev/disk/by-partuuid/blahblahblah_первая_часть
poll_device /dev/disk/by-partuuid/blahblahblah_вторая_часть
poll_device /dev/disk/by-partuuid/blahblahblah_последняя_третья_часть

но у меня вопрос — в том — какое есть ли для этого *стандартное_решение* :-) ..

чтобы самому не редактировать initramfs-скрипт своими велосипедными хуками :-)

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 2)
Ответ на: комментарий от intelfx

Потрясающе. Нет, это точно наркомания.

как-то мне в голову (несколько месяцев назад) залезла мысль — что-то-не-так с этими мультидисковыми-btrfs (по сравнению с LVM и MDADM) ..

я разумеется эту мысль пытался как-то опровергнуть... но вот вплодь по сегоднящний день — так и ни как не получается опровергнуть это :-)

но было бы здорово, хотя

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 2)

вообщем друзья! спасибо что откликнулись!


(кого лишнии раз побеспокоил — прошу прощения ^_^)

думаю что решение моего вопроса — заключается в этом кусочке кода (который *уже* есть в mkinitcpio — в хуке udev):

run_hook() {
    msg ":: Triggering uevents..."
    udevadm trigger --action=add --type=subsystems
    udevadm trigger --action=add --type=devices
    udevadm settle
}

как я понимаю — это заставляет создавать все необходимые ноды (/dev/sd*) — ещё до момента когда будет производиться операция монтирования мультидискового-кореня-btrfs ..

а ожиданием UUID-симлинка ( /dev/disk/by-uuid/blahblahblah — от любого из кусочков ) занимается другая часть кода.. (она тож уже есть).

так как проверить на практике не могу — то остановлюсь на этом :)

единственное что — получается что хук udev — должен запускаться перед хуком btrfs.. чтобы btrfs device scan выполнялся бы уже после того как появятся все ноды /dev/sd* ..

...но вообще если есть какие свежие мысли — то всё равно пишите их :)

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 8)
Ответ на: комментарий от intelfx

В контексте арча это либо скрипт на баше, либо systemd.

чёрт.. прости — только сейчас я *окончательно* понял что ты имел ввиду.. :)

оказывается systemd — это уже *официально* поддерживается для mkinitcpio ... а я неожидал этого.

думаю с приходом systemd в initramfs — описываемая мной проблема — должна окончательно уйти.

потому что одно дело — командой mount монтировать диски. а другое дело — монтировать их через настпление события. (ясное же дело — что через событие это должно происходить более корректно!).

вообще я просто почему-то замыленным взглядом пропустил-мимо-глаз надпись «systemd» в списке хуков mkinitcpio. ну и ты вобщем правильно что упомянул это! :-)

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)

что жы вы со мной делаете, ребята?

уже 4 часа ночи, а я занимаюсь тем что засунул себе в initramfs — этот systemd :-)

но мне он понравился там.. оставлю пожалуй :-) ..[хоть и нет у меня мультидискового-btrfs]

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от user_id_68054

Ты прав, udev — штука полностью асинхронная. Более того, udevadm settle не является решением. Эта команда ждёт, пока udev закончит обработку текущей очереди событий. Проблема в том, что «всех-всех-всех» накопителей не существует: USB-хард можно воткнуть в комп спустя секунду (или десять) после запуска системы, а можно через полчаса. И в каком случае что с ним делать?

Так что settle — не панацея. Если ядро к этому моменту не успеет инициализировать контроллеры, опросить их и сгенерировать соответствующие события — то settle их не заметит.

Поэтому подход в systemd является самым правильным: он связывается с udev'ом и отдельно ждёт каждое устройство в течение заданного таймаута.

Но вот боюсь, что с btrfs и это не поможет... Первый обнаруженный физический раздел (из тех, что составляют мультидисковый том) создаст нужный симлинк, systemd его заметит, попытается смонтировать и, как ты говоришь, обломается, потому что остальных разделов ещё нет. Впрочем, в systemd/udev есть способ это решить: в правиле можно указать ENV{SYSTEMD_READY}=0, и тогда systemd сделает вид, что не заметил соответствующего устройства (пока одно из следующих правил не сделает SYSTEMD_READY=1). Следовательно, вопрос в том, знают ли мейнтейнеры btrfs об этом механизме... Думаю, знают.

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

Поэтому подход в systemd является самым правильным: он связывается с udev'ом и отдельно ждёт каждое устройство в течение заданного таймаута.

Но вот боюсь, что с btrfs и это не поможет... Первый обнаруженный физический раздел (из тех, что составляют мультидисковый том) создаст нужный симлинк, systemd его заметит, попытается смонтировать и, как ты говоришь, обломается, потому что остальных разделов ещё нет.

а может ли быть следующая ситуаця:

1. systemd обнаруживает новый раздел с btrfs..

2. срабатывает событие, и systemd пытается смонтировать, но неудачно (нет всех кусков)..

3. systemd обнаруживает ещё новый раздел с btrfs..

4. опять срабатывает событие, и systemd пытается этот кусочек смонтировать, но опять неудачно (нет всех кусков)..

5. обнаруживается ещё новый раздел с btrfs..

6. опять срабатывает событие, и systemd пытается этот кусочек смонтировать, И УРА, срабатывает успешно!

##################################################

я понимаю что пересичленные действия (1,2,3,4,5,6) — идут не строго попорядку, а некоторые из действий происходят параллельно другим действиям.

но можно ли предположить — что в конечном итоге либо действия 5 и 6 (даже с учётом частично параллельности, и всяких там race condition) — приведут к успешному монтированию в конечном итоге, .. либо более ранние действия (1,2,3,4) приведут к успешному монтированию.

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

а есть где-нибудь док с детальным описанием процесса старта линуксов? (желательно на русском, желательно в разных вариациях)

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

Даже если и есть, то мне таковой неизвестен.

Я знаю только bootup(7) из состава systemd, но он не удовлетворяет ни одному из твоих критериев.

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

Такого быть не может, т. к. systemd, в отличие от udev, не событийно ориентированный. Наоборот — он основан на построении дерева зависимостей.

Как только udev обнаружит первый раздел многодискового тома, он сигнализирует об этом systemd. Тот, в свою очередь, помечает нужный юнит как активный (устройства — тоже юниты). Следом запускается mount-юнит (т. к. все его зависимости удовлетворены), фейлится и следом за ним фейлится всё дерево.

Но, как я уже сказал, есть SYSTEMD_READY — и таки да, этот механизм действительно используется (см. /usr/lib/udev/rules.d/64-btrfs.rules).

Таким образом, если включить systemd в initramfs, всё заработает без рейсов даже в случае медленных устройств и контроллеров (да что там, даже если у тебя корень на флешке, которую ты втыкаешь через полминуты после запуска системы).

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Но, как я уже сказал, есть SYSTEMD_READY — и таки да, этот механизм действительно используется (см. /usr/lib/udev/rules.d/64-btrfs.rules).

прости за глупый вопрос :) .. но....ээээммм...

в каком пакете должен быть этот «rules.d/64-btrfs.rules» ? (в Арчике)

вот тут — нет — https://www.archlinux.org/packages/core/x86_64/btrfs-progs/ .. наверно в другом пакете в каком-то?

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.