Skip to content

Commit

Permalink
systemd port
Browse files Browse the repository at this point in the history
We now fork storage-init as a systemd unit. early systemd-udev
responsibility is now back under the control of systemd. early
switch-root is now back under the control of systemd. logging
is now back under the control of systemd.

Signed-off-by: Eric Curtin <[email protected]>
  • Loading branch information
ericcurtin committed Jan 17, 2024
1 parent 29ff844 commit 7b4d3e0
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 107 deletions.
10 changes: 3 additions & 7 deletions bin/initoverlayfs-install
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

set -e
set -ex

# Constants with default value
CAT="lz4cat"
Expand Down Expand Up @@ -59,9 +59,7 @@ exec_ext4() {
}

detect_initramfs() {
if [ ! -d "${INITRAMFS_DUMP_DIR}" ]; then
mkdir -p "${INITRAMFS_DUMP_DIR}"
fi
mkdir -p "${INITRAMFS_DUMP_DIR}"

echo "Extracting initrd into initoverlayfs..."

Expand Down Expand Up @@ -165,9 +163,7 @@ if ! [ -e "$INITOVERLAYFS_CONF" ] || ! grep -q '[^[:space:]]' "$INITOVERLAYFS_CO
"bootfs $boot_partition" \
"bootfstype ext4" \
"initoverlayfs_builder dracut -H -f -v -M --reproducible -o \"initoverlayfs\"" \
"initrd_builder dracut -H -f -v -M --reproducible -m \"kernel-modules udev-rules initoverlayfs\" -o \"bash systemd systemd-initrd i18n kernel-modules-extra rootfs-block dracut-systemd usrmount base fs-lib microcode_ctl-fw_dir_override shutdown nss-softokn\"" \
"udev_trigger udevadm trigger --type=devices --action=add --subsystem-match=module --subsystem-match=block --subsystem-match=virtio --subsystem-match=pci --subsystem-match=nvme --subsystem-match=mmc --subsystem-match=mmc_host --subsystem-match=platform" \
"udev_trigger_generic udevadm trigger --type=devices --action=add" > $INITOVERLAYFS_CONF
"initrd_builder dracut -H -f -v -M --reproducible -m \"kernel-modules udev-rules initoverlayfs systemd base\" -o \"bash systemd-initrd i18n kernel-modules-extra rootfs-block dracut-systemd usrmount fs-lib microcode_ctl-fw_dir_override shutdown nss-softokn\"" > $INITOVERLAYFS_CONF

erofs_compression_supported="true"
# shellcheck disable=SC2034
Expand Down
24 changes: 3 additions & 21 deletions config-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,9 @@ static inline int conf_construct(conf* c) {
c->fs.scoped = (str*)calloc(1, sizeof(str));
c->fstype.val = (str*)calloc(1, sizeof(str));
c->fstype.scoped = (str*)calloc(1, sizeof(str));
c->udev_trigger.val = (str*)calloc(1, sizeof(str));
c->udev_trigger.scoped = (str*)calloc(1, sizeof(str));
c->udev_trigger_generic.val = (str*)calloc(1, sizeof(str));
c->udev_trigger_generic.scoped = (str*)calloc(1, sizeof(str));
return !c->bootfs.val || !c->bootfs.scoped || !c->bootfstype.val ||
!c->bootfstype.scoped || !c->fs.val || !c->fs.scoped ||
!c->fstype.val || !c->fstype.scoped || !c->udev_trigger.val ||
!c->udev_trigger.scoped || !c->udev_trigger_generic.val ||
!c->udev_trigger_generic.scoped;
!c->fstype.val || !c->fstype.scoped;
}

static inline void set_conf(pair* conf, str** line, const size_t key_len) {
Expand All @@ -42,11 +36,6 @@ static inline void conf_set_pick(conf* c, str** line) {
.len = sizeof("bootfstype") - 1};
const str fs_str = {.c_str = "fs", .len = sizeof("fs") - 1};
const str fstype_str = {.c_str = "fstype", .len = sizeof("fstype") - 1};
const str udev_trigger_str = {.c_str = "udev_trigger",
.len = sizeof("udev_trigger") - 1};
const str udev_trigger_generic_str = {
.c_str = "udev_trigger_generic",
.len = sizeof("udev_trigger_generic") - 1};

if (is_line_key(*line, &bootfs_str))
set_conf(&c->bootfs, line, bootfs_str.len);
Expand All @@ -56,23 +45,16 @@ static inline void conf_set_pick(conf* c, str** line) {
set_conf(&c->fs, line, fs_str.len);
else if (is_line_key(*line, &fstype_str))
set_conf(&c->fstype, line, fstype_str.len);
else if (is_line_key(*line, &udev_trigger_str))
set_conf(&c->udev_trigger, line, udev_trigger_str.len);
else if (is_line_key(*line, &udev_trigger_generic_str))
set_conf(&c->udev_trigger_generic, line, udev_trigger_generic_str.len);
}

static inline conf* conf_print(conf* c) {
#ifdef DEBUG
printd(
"bootfs: {\"%s\", \"%s\"}, bootfstype: {\"%s\", \"%s\"}, fs: {\"%s\", "
"\"%s\"}, fstype: {\"%s\", \"%s\"}, udev_trigger: {\"%s\", \"%s\"}, "
"udev_trigger_generic: {\"%s\", \"%s\"}\n",
"\"%s\"}, fstype: {\"%s\", \"%s\"}\n",
c->bootfs.val->c_str, c->bootfs.scoped->c_str, c->bootfstype.val->c_str,
c->bootfstype.scoped->c_str, c->fs.val->c_str, c->fs.scoped->c_str,
c->fstype.val->c_str, c->fstype.scoped->c_str, c->udev_trigger.val->c_str,
c->udev_trigger.scoped->c_str, c->udev_trigger_generic.val->c_str,
c->udev_trigger_generic.scoped->c_str);
c->fstype.val->c_str, c->fstype.scoped->c_str);
#endif
return c;
}
Expand Down
14 changes: 10 additions & 4 deletions initoverlayfs.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ URL: https://github.com/containers/initoverlayfs
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz

BuildRequires: gcc
Recommends: erofs-utils
Recommends: lz4
Recommends: gzip
Requires: erofs-utils
Requires: dracut

%global debug_package %{nil}
Expand All @@ -26,16 +26,22 @@ gcc ${RPM_OPT_FLAGS} storage-init.c -o storage-init

%install
install -D -m755 bin/initoverlayfs-install ${RPM_BUILD_ROOT}/%{_bindir}/initoverlayfs-install
install -D -m755 storage-init ${RPM_BUILD_ROOT}/%{_prefix}/sbin/storage-init
install -D -m755 lib/dracut/modules.d/81initoverlayfs/module-setup.sh $RPM_BUILD_ROOT/%{_prefix}/lib/dracut/modules.d/81initoverlayfs/module-setup.sh
install -D -m755 storage-init ${RPM_BUILD_ROOT}/%{_sbindir}/storage-init
install -D -m755 lib/dracut/modules.d/81initoverlayfs/module-setup.sh ${RPM_BUILD_ROOT}/%{_prefix}/lib/dracut/modules.d/81initoverlayfs/module-setup.sh
install -D -m644 lib/systemd/system/pre-initoverlayfs.target ${RPM_BUILD_ROOT}/%{_prefix}/lib/systemd/system/pre-initoverlayfs.target
install -D -m644 lib/systemd/system/pre-initoverlayfs.service ${RPM_BUILD_ROOT}/%{_prefix}/lib/systemd/system/pre-initoverlayfs.service
install -D -m644 lib/systemd/system/pre-initoverlayfs-switch-root.service ${RPM_BUILD_ROOT}/%{_prefix}/lib/systemd/system/pre-initoverlayfs-switch-root.service

%files
%license LICENSE
%doc README.md
%attr(0755,root,root)
%{_bindir}/initoverlayfs-install
%{_prefix}/sbin/storage-init
%{_sbindir}/storage-init
%{_prefix}/lib/dracut/modules.d/81initoverlayfs/
%{_prefix}/lib/systemd/system/pre-initoverlayfs.target
%{_prefix}/lib/systemd/system/pre-initoverlayfs.service
%{_prefix}/lib/systemd/system/pre-initoverlayfs-switch-root.service

%changelog
* Thu Dec 14 2023 Stephen Smoogen <[email protected]> - 0.99-1
Expand Down
31 changes: 18 additions & 13 deletions lib/dracut/modules.d/81initoverlayfs/module-setup.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
#!/usr/bin/bash

installkernel() {
hostonly="" instmods erofs overlay
hostonly="" instmods erofs overlay loop
}

# called by dracut
depends() {
echo "systemd"
}

install() {
inst_multiple -o /etc/initoverlayfs.conf
inst_multiple /usr/sbin/storage-init "$systemdutildir"/systemd-udevd \
udevadm modprobe /etc/initoverlayfs.conf
inst_dir /boot /initrofs /overlay /overlay/upper /overlay/work /initoverlayfs

if [ ! -e "/init" ]; then
ln_r /usr/sbin/storage-init "/init"
fi

if [ ! -e "/sbin/init" ]; then
ln_r /usr/sbin/storage-init "/sbin/init"
fi
inst_multiple -o /etc/initoverlayfs.conf /usr/sbin/storage-init \
"$systemdsystemunitdir/pre-initoverlayfs.target" \
"$systemdsystemunitdir/pre-initoverlayfs.service" \
"$systemdsystemunitdir/pre-initoverlayfs-switch-root.service"


inst_dir /boot /initrofs /overlay /overlay/upper /overlay/work \
/initoverlayfs

$SYSTEMCTL -q --root "$initdir" set-default pre-initoverlayfs.target
$SYSTEMCTL -q --root "$initdir" add-wants sysinit.target pre-initoverlayfs.service
$SYSTEMCTL -q --root "$initdir" add-wants sysinit.target pre-initoverlayfs-switch-root.service

> "${initdir}/usr/bin/bash"
}
Expand Down
15 changes: 15 additions & 0 deletions lib/systemd/system/pre-initoverlayfs-switch-root.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[Unit]
Description=Switch Root pre-initoverlayfs
AssertPathExists=/etc/initrd-release
DefaultDependencies=no
ConditionPathExists=/etc/initrd-release
AllowIsolate=yes
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
Before=sysinit.target pre-initoverlayfs.target
After=systemd-journald.service pre-initoverlayfs.service

[Service]
Type=oneshot
ExecStart=systemctl --no-block switch-root /initoverlayfs

18 changes: 18 additions & 0 deletions lib/systemd/system/pre-initoverlayfs.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=pre-initoverlayfs initialization
AssertPathExists=/etc/initrd-release
DefaultDependencies=no
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
Before=sysinit.target pre-initoverlayfs.target
After=systemd-journald.service

[Service]
Type=oneshot
ExecStart=/usr/sbin/storage-init
StandardInput=null
StandardOutput=journal+console
StandardError=journal+console
RemainAfterExit=yes

9 changes: 9 additions & 0 deletions lib/systemd/system/pre-initoverlayfs.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=pre-initoverlayfs Default Target
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
AssertPathExists=/etc/initrd-release
Requires=basic.target
After=pre-initoverlayfs.service rescue.target
AllowIsolate=yes

16 changes: 16 additions & 0 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -ex

REL="$(git tag | tail -1)"
mkdir -p "$HOME/rpmbuild/SOURCES/"
git archive -o "$HOME/rpmbuild/SOURCES/initoverlayfs-$REL.tar.gz" --prefix "initoverlayfs-$REL/" HEAD
./build-scripts/create-spec.sh
rpmbuild_output=$(rpmbuild -bb initoverlayfs.spec 2>&1)
rpm_to_install=$(echo "$rpmbuild_output" | grep "Wrote:" | awk '{print $2}')
if rpm -Uvh "$rpm_to_install"; then
echo "$rpmbuild_output"
fi

initoverlayfs-install

60 changes: 8 additions & 52 deletions storage-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,20 +416,6 @@ static inline int mount_proc_sys_dev(void) {
return 0;
}

static inline pid_t udev_trigger(char** udev_trigger) {
pid_t pid;
if (udev_trigger && *udev_trigger) {
fork_execvp_no_wait(pid, udev_trigger);
return pid;
}

fork_execlp_no_wait(pid, "udevadm", "trigger", "--type=devices",
"--action=add", "--subsystem-match=module",
"--subsystem-match=block", "--subsystem-match=virtio",
"--subsystem-match=pci", "--subsystem-match=nvme");
return pid;
}

static inline bool convert_bootfs(conf* c) {
if (!c->bootfs.val->c_str) {
print("c->bootfs.val.c_str pointer is null\n");
Expand Down Expand Up @@ -509,6 +495,8 @@ static inline int convert_fs(conf* c) {
"redirect_dir=on,lowerdir=/initrofs,upperdir=/overlay/upper,workdir=/" \
"overlay/work"

#define SYSROOT "/initoverlayfs"

static inline void mounts(const conf* c) {
autofree char* dev_loop = 0;
if (c->fs.val->c_str && losetup(&dev_loop, c->fs.val->c_str))
Expand All @@ -521,19 +509,19 @@ static inline void mounts(const conf* c) {
"%d (%s)\n",
dev_loop, c->fstype.val->c_str, errno, strerror(errno));

if (mount("overlay", "/initoverlayfs", "overlay", 0,
if (mount("overlay", SYSROOT, "overlay", 0,
"volatile," OVERLAY_STR) &&
errno == EINVAL &&
mount("overlay", "/initoverlayfs", "overlay", 0, OVERLAY_STR))
mount("overlay", SYSROOT, "overlay", 0, OVERLAY_STR))
print(
"mount(\"overlay\", \"/initoverlayfs\", \"overlay\", 0, \"" OVERLAY_STR
"mount(\"overlay\", \"" SYSROOT "\", \"overlay\", 0, \"" OVERLAY_STR
"\") %d (%s)\n",
errno, strerror(errno));

if (mount("/boot", "/initoverlayfs/boot", c->bootfstype.val->c_str, MS_MOVE,
if (mount("/boot", SYSROOT "/boot", c->bootfstype.val->c_str, MS_MOVE,
NULL))
print(
"mount(\"/boot\", \"/initoverlayfs/boot\", \"%s\", MS_MOVE, NULL) "
"mount(\"/boot\", \"" SYSROOT "/boot\", \"%s\", MS_MOVE, NULL) "
"%d (%s)\n",
c->bootfstype.val->c_str, errno, strerror(errno));
}
Expand Down Expand Up @@ -575,21 +563,6 @@ static inline char** cmd_to_argv(char* cmd) {
}

void wait_mount_bootfs(const conf* c) {
pid_t udev_wait_pid;
fork_execlp_no_wait(udev_wait_pid, "udevadm", "wait", "-t", "8",
c->bootfs.val->c_str);
int status;
waitpid(udev_wait_pid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status)) {
print("optimized udev trigger failed, fall back to generic: %d && %d\n",
WIFEXITED(status), WEXITSTATUS(status));
autofree char** udev_trigger_generic_argv =
cmd_to_argv(c->udev_trigger_generic.val->c_str);
const pid_t udev_trigger_generic_pid =
udev_trigger(udev_trigger_generic_argv);
waitpid(udev_trigger_generic_pid, 0, 0);
}

fork_execlp("udevadm", "wait", c->bootfs.val->c_str);

errno = 0;
Expand All @@ -608,41 +581,24 @@ void exec_init(void) {
}

int main(void) {
mount_proc_sys_dev();
autofclose FILE* kmsg_f_scoped = log_open_kmsg();
kmsg_f = kmsg_f_scoped;
pid_t udevd_pid;
fork_execl_no_wait(udevd_pid, "/lib/systemd/systemd-udevd", "--daemon");
pid_t loop_pid;
fork_execl_no_wait(loop_pid, "/usr/sbin/modprobe", "loop");
autofree_conf conf conf = {.bootfs = {0, 0},
.bootfstype = {0, 0},
.fs = {0, 0},
.fstype = {0, 0},
.udev_trigger = {0, 0},
.udev_trigger_generic = {0, 0}};
.fstype = {0, 0}};
if (conf_construct(&conf))
return 0;

conf_read(&conf, "/etc/initoverlayfs.conf");
autofree char** udev_trigger_argv = cmd_to_argv(conf.udev_trigger.val->c_str);
waitpid(udevd_pid, 0, 0);
const pid_t udev_trigger_pid = udev_trigger(udev_trigger_argv);
const bool do_bootfs = convert_bootfs(&conf);
convert_fs(&conf);
waitpid(udev_trigger_pid, 0, 0);
waitpid(loop_pid, 0, 0);
if (do_bootfs)
wait_mount_bootfs(&conf);

errno = 0;
mounts(&conf);
if (switchroot("/initoverlayfs")) {
print("switchroot(\"/initoverlayfs\") %d (%s)\n", errno, strerror(errno));
return 0;
}

exec_init();

return 0;
}
10 changes: 0 additions & 10 deletions storage-init.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ typedef struct conf {
pair bootfstype;
pair fs;
pair fstype;
pair udev_trigger;
pair udev_trigger_generic;
} conf;

static inline void cleanup_free_conf(conf* p) {
Expand All @@ -76,23 +74,15 @@ static inline void cleanup_free_conf(conf* p) {
free(p->fs.scoped->c_str);
if (p->fstype.scoped)
free(p->fstype.scoped->c_str);
if (p->udev_trigger.scoped)
free(p->udev_trigger.scoped->c_str);
if (p->udev_trigger_generic.scoped)
free(p->udev_trigger_generic.scoped->c_str);

free(p->bootfs.scoped);
free(p->bootfstype.scoped);
free(p->fs.scoped);
free(p->fstype.scoped);
free(p->udev_trigger.scoped);
free(p->udev_trigger_generic.scoped);
free(p->bootfs.val);
free(p->bootfstype.val);
free(p->fs.val);
free(p->fstype.val);
free(p->udev_trigger.val);
free(p->udev_trigger_generic.val);
}

static inline void cleanup_free(void* p) {
Expand Down

0 comments on commit 7b4d3e0

Please sign in to comment.