[make-initrd] polld и проверка наличия /root/sbin/init

Leonid Krivoshein klark.devel at gmail.com
Fri Apr 7 01:27:13 MSK 2023


On 4/6/23 09:00, Leonid Krivoshein wrote:
>> Отсюда выводы:
>> 1. Факт монтирования корня недостаточное условие, существует 
>> переходный процесс монтирования
>
> Насколько я понимаю, у каждой группы процессов может быть собственное 
> пространство имён монтирования, но описываемое поведение говорит о 
> том, что polld и chaind находятся в разных пространствах имён и ещё 
> что-то заставляет перемещать структуры в ядре от одной из групп к 
> другой. В общем странно и невероятно, потому что по идее, если 
> пространства разные, они изолированы, а если одинаковые, все процессы 
> должны увидеть изменения мгновенно. Тем не менее, мы наблюдаем именно 
> такое поведение, описанное Антоном. Весьма похоже на ядерный рейс, 
> поскольку на начальном этапе загрузка работой сильная и "мгновенности" 
> не случается. 

Сказанное выше больше похоже на тонкую шутку. На самом деле всё может 
быть проще...

Если какой-то внешний процесс по отношению bootchain среагировал на 
событие, увидев /root/sbin/init или что-то ещё, он же может вызвать 
telinit 2? Но на шаге squahfs это ещё не было финальным монтированием. В 
тот же момент bootchain продолжает процесс загрузки в шаге overlayfs, но 
polld, получив сигнал, уже начинает проверку финального условия.

bootchain выполняет telinit 2 только на последнем шаге rootfs, и раз 
polld начинает обработку раньше, сигнал посылает кто-то ещё и это 
следует из журнала chaind.log. Возможно, остановка polld на время работы 
bootchain поможет, я просто не знаю, можно ли это делать. Но я 
сталкивался с двойной обработкой события на финальном этапе в другом 
коде при использовании как раз метода загрузки.

При написании прототипа отдельной фичи overlayroot (вложил), закрывающей 
обычный корень на запись, приходится проверять повторный вход в 
/lib/initrd/boot/scripts/overlayroot. Без это оверлеи монтируются 
неправильно и система просто не грузится. А откуда возникает второе 
событие при срабатывании события "корень найден -- пора в stage2"? 
Раньше я полагал, что его создаёт монтирование overlay.

Драка между bootchain и polld может быть не результатом "гонки" в ядре 
или сторонним вызовом telinit 2, а результатом обработки этого второго 
события. Но я не так хорошо знаю архитектуру make-initrd.


-- 
WBR, Leonid Krivoshein.
-------------- next part --------------
#!/bin/sh -efu

. shell-error

OVERLAY="${1:-tmpfs}"
BASE=/usr/share/make-initrd/data

case "$OVERLAY" in
-i|--install)
	OVERLAY="${2:-tmpfs}"
	;;

-u|--uninstall)
	[ -d "$BASE/lib/initrd/boot/scripts" ] ||
		fatal "make-initrd is not installed."
	[ -x "$BASE/lib/initrd/boot/scripts/$PROG" ] ||
		fatal "The $PROG feature is not installed."
	sed -i -E "/\.\/$PROG/d" "$BASE"/lib/initrd/boot/method/localdev/check
	sed -i -E "/register_parameter string OVERLAYROOT/d" \
			"$BASE"/etc/initrd/cmdline.d/base
	sed -i -E "/MODULES_TRY_ADD \+= overlay/d" /etc/initrd.mk
	sed -i -E "/PUT_FILES \+= \/etc\/$PROG\.conf/d" /etc/initrd.mk
	rm -f -- "/etc/$PROG.conf" "$BASE/lib/initrd/boot/scripts/$PROG"
	echo "The $PROG feature was uninstalled!"
	exit 0
	;;

-h|--help)
	cat <<-EOF
	Usage $PROG [<command> | UUID=... | LABEL=... | <device>]

	Commands:
	  -i, --install     Install $PROG feature.
	  -u, --uninstall   Uninstall $PROG feature.
	  -h, --help        Show this help message and exit.

	UUID=, LABEL= and /dev/device specified a device with the R/W layer.
	By default R/W layer will be created on the TMPFS at the install time.
	After install or uninstall don't forget to run make-initrd [<args>]...
	EOF
	exit 0
	;;
esac

# Install feature
[ -d "$BASE/lib/initrd/boot/scripts" ] ||
	fatal "make-initrd is not installed."
[ ! -f "$BASE/lib/initrd/boot/scripts/$PROG" ] ||
	fatal "The $PROG feature already installed."
grep -qw "./$PROG" "$BASE"/lib/initrd/boot/method/localdev/check ||
	echo "./$PROG" >> "$BASE"/lib/initrd/boot/method/localdev/check
grep -qw "OVERLAYROOT" "$BASE"/etc/initrd/cmdline.d/base ||
	echo "register_parameter string OVERLAYROOT" \
		>> "$BASE"/etc/initrd/cmdline.d/base
echo "$PROG=$OVERLAY" > "/etc/$PROG.conf"
grep -qw "/etc/$PROG.conf" /etc/initrd.mk ||
	echo "PUT_FILES += /etc/$PROG.conf" >> /etc/initrd.mk
grep -w "MODULES_TRY_ADD" /etc/initrd.mk |grep -qw overlay ||
	echo "MODULES_TRY_ADD += overlay" >> /etc/initrd.mk
cat > "$BASE/lib/initrd/boot/scripts/$PROG" <<EOF
#!/bin/bash -efu

. shell-error
. /.initrd/initenv

# Handle first event only
[ ! -f /.initrd/$PROG ] ||
	exit 0
[ -n "\${$PROG-}" ] || [ ! -s /etc/$PROG.conf ] ||
	. /etc/$PROG.conf
:> /.initrd/$PROG

case "\${$PROG-}" in
"")	# Silent use default boot
	exit 0
	;;
disabled)
	echo "rootfs has return back to the read/write mode" >&2
	exit 0
	;;
tmpfs)
	echo "rootfs switched to the read-only mode, using tmpfs as overlay" >&2
	device=
	;;
UUID=?*)
	device="/dev/disk/by-uuid/\${$PROG##UUID=}"
	;;
LABEL=?*)
	device="/dev/disk/by-label/\${$PROG##LABEL=}"
	;;
/dev/?*)
	device="\$$PROG"
	;;
*)
	fatal "\$$PROG: invalid $PROG"
	;;
esac

# Wait the device
if [ -n "\$device" ]; then
	i=10

	while [ "\$i" != 0 ]; do
		dev="\$(readlink-e "\$device" 2>/dev/null ||:)"
		[ -z "\$dev" ] || [ ! -b "\$dev" ] ||
			break
		i="\$((\$i - 1))"
		sleep .5
	done

	[ -n "\$dev" ] && [ -b "\$dev" ] ||
		fatal "\$$PROG: invalid device specification"
	echo "rootfs switched to the read-only mode, using \$dev as overlay" >&2
	device="\$dev"
fi

echo "remounting / with overlayfs" >&2

mkdir -p -- "\$rootmnt.rw" "\$rootmnt.ro"

if [ -n "\$device" ]; then
	mount -- "\$device" "\$rootmnt.rw"
else
	mount -t tmpfs -o mode=755 -- none "\$rootmnt.rw"
fi

opts="lowerdir=\$rootmnt.ro"
opts="\$opts,upperdir=\$rootmnt.rw/rw"
opts="\$opts,workdir=\$rootmnt.rw/wk"

mkdir -p -- "\$rootmnt.rw/rw" "\$rootmnt.rw/wk"
mount --move -- "\$rootmnt" "\$rootmnt.ro"
mount -t overlay -o "\$opts" -- overlay "\$rootmnt"
mkdir -p -- "\$rootmnt/.ro" "\$rootmnt/.rw"
mount --move -- "\$rootmnt.ro" "\$rootmnt/.ro"
mount --move -- "\$rootmnt.rw" "\$rootmnt/.rw"
rmdir -- "\$rootmnt.rw" "\$rootmnt.ro"

echo "rootfs overlayed with overlayfs" >&2
EOF
chmod +x "$BASE/lib/initrd/boot/scripts/$PROG"
echo "The $PROG feature was installed!"


More information about the Make-initrd mailing list