diff --git a/contrib/fstab.bb b/contrib/fstab.bb new file mode 100644 index 00000000..672bd0f6 --- /dev/null +++ b/contrib/fstab.bb @@ -0,0 +1,15 @@ +# This is a basic /etc/fstab that mounts up all of the virtual filesystems +# that older versions of Finit used to mount internally. It can serve as a +# starting point for systems running Busybox's mount implementation. Make +# sure that CONFIG_FEATURE_MOUNT_HELPERS enabled; as this is required +# create the /dev/{pts,shm} directories. + +devtmpfs /dev devtmpfs defaults 0 0 +mkdir#-p /dev/pts helper none 0 0 +devpts /dev/pts devpts mode=620,ptmxmode=0666 0 0 +mkdir#-p /dev/shm helper none 0 0 +tmpfs /dev/shm tmpfs mode=0777 0 0 +proc /proc proc defaults 0 0 +tmpfs /tmp tmpfs mode=1777,nosuid,nodev 0 0 +tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0 +sysfs /sys sysfs defaults 0 0 diff --git a/src/finit.c b/src/finit.c index db1637f3..423cfb50 100644 --- a/src/finit.c +++ b/src/finit.c @@ -124,6 +124,80 @@ static int fsck(int pass) return rc; } +static int fsck_all(void) +{ + int pass, rc = 0; + + for (pass = 1; pass < 10; pass++) { + rc = fsck(pass); + if (rc) + break; + } + + return rc; +} + +#ifndef SYSROOT +static void fs_remount_root(int fsckerr) +{ + struct fstab *fs; + + if (!setfsent()) + return; + + while ((fs = getfsent())) { + if (!strcmp(fs->fs_file, "/")) + break; + } + + /* If / is not listed in fstab, or listed as 'ro', leave it + * alone. */ + if (!fs || !strcmp(fs->fs_type, "ro")) + goto out; + + if (fsckerr) + print(1, "Cannot remount / as read-write, fsck failed before"); + else + run_interactive("mount -n -o remount,rw /", + "Remounting / as read-write"); + +out: + endfsent(); +} +#else +static void fs_remount_root(int fsckerr) +{ + /* + * XXX: Untested, in the initramfs age we should + * probably use switch_root instead. + */ + rc = mount(SYSROOT, "/", NULL, MS_MOVE, NULL); +} +#endif /* SYSROOT */ + +static void fs_init(void) +{ + int fsckerr; + + if (!rescue) { + fsckerr = fsck_all(); + fs_remount_root(fsckerr); + } + + + _d("Root FS up, calling hooks ..."); + plugin_run_hooks(HOOK_ROOTFS_UP); + + if (run_interactive("mount -na", "Mounting filesystems")) + plugin_run_hooks(HOOK_MOUNT_ERROR); + + _d("Calling extra mount hook, after mount -a ..."); + plugin_run_hooks(HOOK_MOUNT_POST); + + run("swapon -ea"); + umask(0022); +} + /* * If everything goes south we can use this to give the operator an * emergency shell to debug the problem -- Finit should not crash! @@ -274,7 +348,6 @@ int main(int argc, char *argv[]) uev_ctx_t loop; char cmd[256]; char *path; - int rc = 0; /* * finit/init/telinit client tool uses /dev/initctl pipe @@ -313,86 +386,22 @@ int main(int argc, char *argv[]) */ emergency_shell(); + /* + * Hello world. + */ + banner(); + /* * Initial setup of signals, ignore all until we're up. */ sig_init(); - /* - * Mount base file system - */ - if (!fismnt("/proc") && mount("none", "/proc", "proc", 0, NULL)) - _pe("Failed mounting /proc"); - if (fisdir("/proc/bus/usb")) - mount("none", "/proc/bus/usb", "usbfs", 0, NULL); - /* * Load plugins early, finit.conf may contain references to * features implemented by plugins. */ plugin_init(&loop); - /* - * Hello world. - */ - banner(); - - /* - * Check file systems listed with pass > 0 in /etc/fstab - */ - rc = 0; - for (int pass = 1; pass < 10 && !rescue; pass++) { - rc = fsck(pass); - if (rc) - break; - } - - /* - * Mount filesystems - */ - if (!rescue) { -#ifndef SYSROOT - /* - * Remount / read-write if it exists in fstab is not 'ro'. - * This is what the Debian sysv initscripts does. - */ - if (setfsent()) { - struct fstab *fs; - - while ((fs = getfsent())) { - if (strcmp(fs->fs_file, "/")) - continue; - - if (strcmp(fs->fs_type, "ro")) { - if (rc) - print(1, "Cannot remount / as read-write, fsck failed before"); - else - rc = run_interactive("mount -n -o remount,rw /", "Remounting / as read-write"); - } - break; - } - - endfsent(); - } -#else - /* - * XXX: Untested, in the initramfs age we should - * probably use switch_root instead. - */ - rc = mount(SYSROOT, "/", NULL, MS_MOVE, NULL); -#endif - } - - /* Create /sys if missing, some systems don't include it in their rootfs skeleton */ - if (!rc && !fisdir("/sys")) - mkdir("/sys", 0755); - - /* Only mount /sys if it's not already mounted */ - if (!fismnt("/sys") && mount("none", "/sys", "sysfs", 0, NULL)) { - print(1, "Cannot mount /sys, your system may behave unusually"); - _pe("Failed mounting /sys"); - } - /* * Initialize default control groups, if available */ @@ -404,40 +413,16 @@ int main(int argc, char *argv[]) */ conf_init(); - /* - * Some non-embedded systems without an initramfs may not have /dev mounted yet - * If they do, check if system has udevadm and perform cleanup from initramfs - */ - if (!fismnt("/dev")) - mount("udev", "/dev", "devtmpfs", MS_RELATIME, "size=10%,nr_inodes=61156,mode=755"); - else if (whichp("udevadm")) - run_interactive("udevadm info --cleanup-db", "Cleaning up udev db"); - - /* Modern systems use /dev/pts */ - makedir("/dev/pts", 0755); - mount("devpts", "/dev/pts", "devpts", 0, "gid=5,mode=620,ptmxmode=0666"); - - /* - * Some systems rely on us to both create /dev/shm and, to mount - * a tmpfs there. Any system with dbus needs shared memory, so - * mount it, unless its already mounted, but not if listed in - * the /etc/fstab file already. - */ - makedir("/dev/shm", 0755); - if (!fismnt("/dev/shm") && !ismnt("/etc/fstab", "/dev/shm", NULL)) - mount("shm", "/dev/shm", "tmpfs", 0, "mode=0777"); - - /* - * New tmpfs based /run for volatile runtime data - * For details, see http://lwn.net/Articles/436012/ - */ - if (fisdir("/run") && !fismnt("/run")) - mount("tmpfs", "/run", "tmpfs", MS_NODEV | MS_NOSUID | MS_NOEXEC, "mode=0755,size=10%"); - umask(022); + fs_init(); /* Bootstrap conditions, needed for hooks */ cond_init(); + /* Emit conditions for early hooks that ran before the + * condition system was initialized in case anyone . */ + cond_set_oneshot(plugin_hook_str(HOOK_BANNER)); + cond_set_oneshot(plugin_hook_str(HOOK_ROOTFS_UP)); + /* * Populate /dev and prepare for runtime events from kernel. * Prefer udev if mdev is also available on the system. @@ -488,21 +473,6 @@ int main(int argc, char *argv[]) wdog = svc_find(FINIT_LIBPATH_ "/watchdogd", NULL); } - if (!rescue) { - _d("Root FS up, calling hooks ..."); - plugin_run_hooks(HOOK_ROOTFS_UP); - - umask(0); - if (run_interactive("mount -na", "Mounting filesystems")) - plugin_run_hooks(HOOK_MOUNT_ERROR); - - _d("Calling extra mount hook, after mount -a ..."); - plugin_run_hooks(HOOK_MOUNT_POST); - - run("swapon -ea"); - umask(0022); - } - /* Base FS up, enable standard SysV init signals */ sig_setup(&loop); diff --git a/src/plugin.c b/src/plugin.c index 85285b3a..e5bc019e 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -201,7 +201,12 @@ void plugin_run_hook(hook_point_t no, void *arg) } } - cond_set_oneshot(hook_cond[no]); + /* Conditions are stored in /run, so don't try to signal + * conditions for any hooks before filesystems have been + * mounted. */ + if (no >= HOOK_MOUNT_ERROR) + cond_set_oneshot(hook_cond[no]); + service_step_all(SVC_TYPE_RUNTASK); }