diff --git a/bin/initoverlayfs-install b/bin/initoverlayfs-install index 6fc8f72..eb3443f 100755 --- a/bin/initoverlayfs-install +++ b/bin/initoverlayfs-install @@ -17,7 +17,7 @@ exec_erofs() { "$SKIPCPIO_BIN" "/boot/initramfs-$kver.img" | "$CAT" | cpio -ivd popd rm -f "/boot/initoverlayfs-$kver.img" - mkfs.erofs "$erofs_compression" "/boot/initoverlayfs-$kver.img" ${INITRAMFS_DUMP_DIR} + mkfs.erofs $erofs_compression "/boot/initoverlayfs-$kver.img" ${INITRAMFS_DUMP_DIR} } # Support for ext4 is currently under development. @@ -138,14 +138,15 @@ if [ -z "$kver" ]; then kver="$(uname -r)" fi -if ! [ -e "$INITOVERLAYFS_CONF" ]; then +if ! [ -e "$INITOVERLAYFS_CONF" ] || ! grep -q '[^[:space:]]' "$INITOVERLAYFS_CONF"; then boot_partition=$(< /etc/fstab grep "/boot.*ext4" | awk '{print $1}') - printf "%s\n%s\n%s\n%s\n%s\n" \ + printf "%s\n%s\n%s\n%s\n%s\n%s\n" \ "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" > $INITOVERLAYFS_CONF + "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 erofs_compression_supported="true" . /etc/os-release diff --git a/config-parser.h b/config-parser.h index 4ea34f4..3db1650 100644 --- a/config-parser.h +++ b/config-parser.h @@ -14,10 +14,13 @@ static inline int conf_construct(conf* c) { 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.scoped || !c->udev_trigger_generic.val || + !c->udev_trigger_generic.scoped; } static inline void set_conf(pair* conf, str** line, const size_t key_len) { @@ -41,6 +44,9 @@ static inline void conf_set_pick(conf* c, str** line) { 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); @@ -52,17 +58,21 @@ static inline void conf_set_pick(conf* c, str** line) { 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\"}\n", + "\"%s\"}, fstype: {\"%s\", \"%s\"}, udev_trigger: {\"%s\", \"%s\"}, " + "udev_trigger_generic: {\"%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.scoped->c_str, c->udev_trigger_generic.val->c_str, + c->udev_trigger_generic.scoped->c_str); #endif return c; } diff --git a/storage-init.c b/storage-init.c index 76bea66..68acfef 100644 --- a/storage-init.c +++ b/storage-init.c @@ -596,21 +596,36 @@ int main(void) { .bootfstype = {0, 0}, .fs = {0, 0}, .fstype = {0, 0}, - .udev_trigger = {0, 0}}; + .udev_trigger = {0, 0}, + .udev_trigger_generic = {0, 0}}; if (conf_construct(&conf)) return 0; conf_read(&conf, "/etc/initoverlayfs.conf"); - autofree char** udev_argv = cmd_to_argv(conf.udev_trigger.val->c_str); + 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_argv); + const pid_t udev_trigger_pid = udev_trigger(udev_trigger_argv); convert_bootfs(&conf); convert_fs(&conf); waitpid(udev_trigger_pid, 0, 0); waitpid(loop_pid, 0, 0); + pid_t udev_wait_pid; + fork_execlp_no_wait(udev_wait_pid, "udevadm", "wait", "-t", "8", + conf.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(conf.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", conf.bootfs.val->c_str); errno = 0; - mounts(&conf); if (switchroot("/initoverlayfs")) { print("switchroot(\"/initoverlayfs\") %d (%s)\n", errno, strerror(errno)); diff --git a/storage-init.h b/storage-init.h index f044987..06bdef2 100644 --- a/storage-init.h +++ b/storage-init.h @@ -64,6 +64,7 @@ typedef struct conf { pair fs; pair fstype; pair udev_trigger; + pair udev_trigger_generic; } conf; static inline void cleanup_free_conf(conf* p) { @@ -77,17 +78,21 @@ static inline void cleanup_free_conf(conf* p) { 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) {