kumquat-buildroot/package/skeleton-init-systemd/skeleton-init-systemd.mk

69 lines
2.3 KiB
Makefile
Raw Normal View History

################################################################################
#
# skeleton-init-systemd
#
################################################################################
# The skeleton can't depend on the toolchain, since all packages depends on the
# skeleton and the toolchain is a target package, as is skeleton.
# Hence, skeleton would depends on the toolchain and the toolchain would depend
# on skeleton.
SKELETON_INIT_SYSTEMD_ADD_TOOLCHAIN_DEPENDENCY = NO
SKELETON_INIT_SYSTEMD_ADD_SKELETON_DEPENDENCY = NO
SKELETON_INIT_SYSTEMD_DEPENDENCIES = skeleton-init-common
SKELETON_INIT_SYSTEMD_PROVIDES = skeleton
system: make systemd work on a read-only rootfs When the rootfs is readonly, systemd will expect /var to be writable. Because we do not really have a R/W filesystem to mount on /var, we make it a tmpfs [*], and use the systemd-tmpfiles feature to populate it with "factory" defaults. We obtain those factory defaults by redirecting /var to that location at build time, using a symlink /var -> /usr/share/factory which is the location in which systemd-tmpfiles will look for when instructed to "recursively copy" a directory. With a line like: C /var/something - - - - it will look for /usr/share/factory/something and copy it (recursively if it is a directory) to /var/something, but only if it does not already exist there. We also mark this copy with the exclamation mark, as it is only safe to copy on boot, not when changing targets. To be noted: the real format for such lines are: C /var/something - - - - /from/where/to/copy/something But if the source is not given, then it is implicitly taken from /usr/share/factory (which in our case is as-good a location as whatever else, so we use it, and thus we need not specify the source of the copy). Note that we treat symlinks a little bit specially, by creating symlinks to the factory defaults rather than copying them. Finally, /var at build time is a symlink, but at runtime, it must be a directory (so we can mount the tmpfs over there). We can't change that as a target-finalize hook, because: - some packages may want to set ownership and/or access rights on files or directories in /var, and that only happens while assembling the filesystem images; changing /var from a symlink to a (then empty) directory would break this; - /var would be a directory on sub-sequent builds (until the next "make clean"). Instead, we use the newly-introduce pre- and post-rootfs command hooks, to turn /var into a directory before assembling the image, and back to a symlink after assembling the image. [*] People who want the factory-defaults only on first boot will have to tweak the fstab to mount something else than a tmpfs on /var. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Reviewed-by: Romain Naour <romain.naour@gmail.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2017-08-02 00:52:23 +02:00
ifeq ($(BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW),y)
define SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW
system: make systemd work on a read-only rootfs When the rootfs is readonly, systemd will expect /var to be writable. Because we do not really have a R/W filesystem to mount on /var, we make it a tmpfs [*], and use the systemd-tmpfiles feature to populate it with "factory" defaults. We obtain those factory defaults by redirecting /var to that location at build time, using a symlink /var -> /usr/share/factory which is the location in which systemd-tmpfiles will look for when instructed to "recursively copy" a directory. With a line like: C /var/something - - - - it will look for /usr/share/factory/something and copy it (recursively if it is a directory) to /var/something, but only if it does not already exist there. We also mark this copy with the exclamation mark, as it is only safe to copy on boot, not when changing targets. To be noted: the real format for such lines are: C /var/something - - - - /from/where/to/copy/something But if the source is not given, then it is implicitly taken from /usr/share/factory (which in our case is as-good a location as whatever else, so we use it, and thus we need not specify the source of the copy). Note that we treat symlinks a little bit specially, by creating symlinks to the factory defaults rather than copying them. Finally, /var at build time is a symlink, but at runtime, it must be a directory (so we can mount the tmpfs over there). We can't change that as a target-finalize hook, because: - some packages may want to set ownership and/or access rights on files or directories in /var, and that only happens while assembling the filesystem images; changing /var from a symlink to a (then empty) directory would break this; - /var would be a directory on sub-sequent builds (until the next "make clean"). Instead, we use the newly-introduce pre- and post-rootfs command hooks, to turn /var into a directory before assembling the image, and back to a symlink after assembling the image. [*] People who want the factory-defaults only on first boot will have to tweak the fstab to mount something else than a tmpfs on /var. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Reviewed-by: Romain Naour <romain.naour@gmail.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2017-08-02 00:52:23 +02:00
echo "/dev/root / auto rw 0 1" >$(TARGET_DIR)/etc/fstab
endef
else
# On a R/O rootfs, /var is a tmpfs filesystem. So, at build time, we
# redirect /var to the "factory settings" location. Just before the
# filesystem gets created, the /var symlink will be replaced with
# a real (but empty) directory, and the "factory files" will be copied
# back there by the tmpfiles.d mechanism.
define SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW
system: make systemd work on a read-only rootfs When the rootfs is readonly, systemd will expect /var to be writable. Because we do not really have a R/W filesystem to mount on /var, we make it a tmpfs [*], and use the systemd-tmpfiles feature to populate it with "factory" defaults. We obtain those factory defaults by redirecting /var to that location at build time, using a symlink /var -> /usr/share/factory which is the location in which systemd-tmpfiles will look for when instructed to "recursively copy" a directory. With a line like: C /var/something - - - - it will look for /usr/share/factory/something and copy it (recursively if it is a directory) to /var/something, but only if it does not already exist there. We also mark this copy with the exclamation mark, as it is only safe to copy on boot, not when changing targets. To be noted: the real format for such lines are: C /var/something - - - - /from/where/to/copy/something But if the source is not given, then it is implicitly taken from /usr/share/factory (which in our case is as-good a location as whatever else, so we use it, and thus we need not specify the source of the copy). Note that we treat symlinks a little bit specially, by creating symlinks to the factory defaults rather than copying them. Finally, /var at build time is a symlink, but at runtime, it must be a directory (so we can mount the tmpfs over there). We can't change that as a target-finalize hook, because: - some packages may want to set ownership and/or access rights on files or directories in /var, and that only happens while assembling the filesystem images; changing /var from a symlink to a (then empty) directory would break this; - /var would be a directory on sub-sequent builds (until the next "make clean"). Instead, we use the newly-introduce pre- and post-rootfs command hooks, to turn /var into a directory before assembling the image, and back to a symlink after assembling the image. [*] People who want the factory-defaults only on first boot will have to tweak the fstab to mount something else than a tmpfs on /var. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Reviewed-by: Romain Naour <romain.naour@gmail.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2017-08-02 00:52:23 +02:00
mkdir -p $(TARGET_DIR)/etc/systemd/tmpfiles.d
echo "/dev/root / auto ro 0 1" >$(TARGET_DIR)/etc/fstab
echo "tmpfs /var tmpfs mode=1777 0 0" >>$(TARGET_DIR)/etc/fstab
endef
define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
package/skeleton-systemd: invert factory logic Currently, we handle the factory by redirectoring /var with a symlink at build time, and with some trickery during the filesystem generation, depending on whether we need to remount the filesystem read-write or not. However, this is causing quite some pain with the latest systemd, now that they have moved their dbus socket to /run instead of /var/run. As such, trying to play tricks with /var/run as a symlink is difficult, because at times it is in .usr/share/factory/var/run (during build) and then it is in /var/run (at runtime). So a relative symlink is not possible. But an absolute symlink is not possible either, because we are installing out-of-tree. Oh the joys of cross-compilation... :-) We fix all this mess by making /var a real directory from the onset, so that we can use the runtime-expected layout even during the build. Then, during filesystem generation, we move /var away to the factory, and populate it as we used to do. This still requires a post-fs hook to restore /var after the filesystem generation. This leaves a situation that, should the filesystem generation fails, /var will be left in an inconsistent state. But that is not worse than what we already had anyway. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Cc: Trent Piepho <tpiepho@impinj.com> Cc: Adam Duskett <aduskett@gmail.com> Cc: Romain Naour <romain.naour@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2018-03-04 18:06:16 +01:00
rm -rf $(TARGET_DIR)/usr/share/factory/var
mv $(TARGET_DIR)/var $(TARGET_DIR)/usr/share/factory/var
mkdir -p $(TARGET_DIR)/var
package/skeleton-init-systemd: work around for /var/lib not populating When using a RO root with systemd, it is intended that /var/lib should be populated at boot time by tmpfiles system mirroring it from /usr/share/factory/var/lib. However, this will only happen if /var/lib does not already exist at the time systemd-tmpfiles runs. If it does exist, then tmpfiles will (silently) skip it and do nothing. It turns out /var/lib will exist, because some part of systemd creates /var/lib/systemd/catalog on boot before tmpfiles runs. The fix used here is to also create tmpfiles entries for the contents of /var/lib/* and /var/lib/systemd/*. This way, when those directories already exist, the entire tree is not skipped and instead the not-yet-existing contents of /var/lib and /var/lib/systemd will be still be mirrored from the factory dir. And if /var/lib/systemd, or a prefix of that, stops getting created and does not exist, it'll still mirror properly. It does cause some warnings from systemd: systemd[1]: Starting Create Volatile Files and Directories... systemd-tmpfiles[148]: [/etc/tmpfiles.d/var-factory.conf:7] Duplicate line for path "/var/lib/systemd", ignoring. systemd-tmpfiles[148]: [/etc/tmpfiles.d/var-factory.conf:8] Duplicate line for path "/var/lib/systemd/coredump", ignoring. But they can be ignored. IMHO, I think a better solution would be for systemd-tmpfiles to gain a "merge tree" operation that is like "C" but doesn't abort if the destination exists, but rather merges the source into it. Signed-off-by: Trent Piepho <tpiepho@impinj.com> [yann.morin.1998@free.fr: slight rework of commit title] Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr> Tested-by: Adam Duskett <aduskett@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2018-03-04 18:06:15 +01:00
for i in $(TARGET_DIR)/usr/share/factory/var/* \
$(TARGET_DIR)/usr/share/factory/var/lib/* \
$(TARGET_DIR)/usr/share/factory/var/lib/systemd/*; do \
[ -e "$${i}" ] || continue; \
system: make systemd work on a read-only rootfs When the rootfs is readonly, systemd will expect /var to be writable. Because we do not really have a R/W filesystem to mount on /var, we make it a tmpfs [*], and use the systemd-tmpfiles feature to populate it with "factory" defaults. We obtain those factory defaults by redirecting /var to that location at build time, using a symlink /var -> /usr/share/factory which is the location in which systemd-tmpfiles will look for when instructed to "recursively copy" a directory. With a line like: C /var/something - - - - it will look for /usr/share/factory/something and copy it (recursively if it is a directory) to /var/something, but only if it does not already exist there. We also mark this copy with the exclamation mark, as it is only safe to copy on boot, not when changing targets. To be noted: the real format for such lines are: C /var/something - - - - /from/where/to/copy/something But if the source is not given, then it is implicitly taken from /usr/share/factory (which in our case is as-good a location as whatever else, so we use it, and thus we need not specify the source of the copy). Note that we treat symlinks a little bit specially, by creating symlinks to the factory defaults rather than copying them. Finally, /var at build time is a symlink, but at runtime, it must be a directory (so we can mount the tmpfs over there). We can't change that as a target-finalize hook, because: - some packages may want to set ownership and/or access rights on files or directories in /var, and that only happens while assembling the filesystem images; changing /var from a symlink to a (then empty) directory would break this; - /var would be a directory on sub-sequent builds (until the next "make clean"). Instead, we use the newly-introduce pre- and post-rootfs command hooks, to turn /var into a directory before assembling the image, and back to a symlink after assembling the image. [*] People who want the factory-defaults only on first boot will have to tweak the fstab to mount something else than a tmpfs on /var. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Reviewed-by: Romain Naour <romain.naour@gmail.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2017-08-02 00:52:23 +02:00
j="$${i#$(TARGET_DIR)/usr/share/factory}"; \
if [ -L "$${i}" ]; then \
printf "L+! %s - - - - %s\n" \
"$${j}" "../usr/share/factory/$${j}" \
|| exit 1; \
else \
printf "C! %s - - - -\n" "$${j}" \
|| exit 1; \
fi; \
done >$(TARGET_DIR)/etc/tmpfiles.d/var-factory.conf
endef
SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS += SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
system: make systemd work on a read-only rootfs When the rootfs is readonly, systemd will expect /var to be writable. Because we do not really have a R/W filesystem to mount on /var, we make it a tmpfs [*], and use the systemd-tmpfiles feature to populate it with "factory" defaults. We obtain those factory defaults by redirecting /var to that location at build time, using a symlink /var -> /usr/share/factory which is the location in which systemd-tmpfiles will look for when instructed to "recursively copy" a directory. With a line like: C /var/something - - - - it will look for /usr/share/factory/something and copy it (recursively if it is a directory) to /var/something, but only if it does not already exist there. We also mark this copy with the exclamation mark, as it is only safe to copy on boot, not when changing targets. To be noted: the real format for such lines are: C /var/something - - - - /from/where/to/copy/something But if the source is not given, then it is implicitly taken from /usr/share/factory (which in our case is as-good a location as whatever else, so we use it, and thus we need not specify the source of the copy). Note that we treat symlinks a little bit specially, by creating symlinks to the factory defaults rather than copying them. Finally, /var at build time is a symlink, but at runtime, it must be a directory (so we can mount the tmpfs over there). We can't change that as a target-finalize hook, because: - some packages may want to set ownership and/or access rights on files or directories in /var, and that only happens while assembling the filesystem images; changing /var from a symlink to a (then empty) directory would break this; - /var would be a directory on sub-sequent builds (until the next "make clean"). Instead, we use the newly-introduce pre- and post-rootfs command hooks, to turn /var into a directory before assembling the image, and back to a symlink after assembling the image. [*] People who want the factory-defaults only on first boot will have to tweak the fstab to mount something else than a tmpfs on /var. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Reviewed-by: Romain Naour <romain.naour@gmail.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2017-08-02 00:52:23 +02:00
endif
define SKELETON_INIT_SYSTEMD_INSTALL_TARGET_CMDS
mkdir -p $(TARGET_DIR)/home
mkdir -p $(TARGET_DIR)/srv
package/skeleton-systemd: invert factory logic Currently, we handle the factory by redirectoring /var with a symlink at build time, and with some trickery during the filesystem generation, depending on whether we need to remount the filesystem read-write or not. However, this is causing quite some pain with the latest systemd, now that they have moved their dbus socket to /run instead of /var/run. As such, trying to play tricks with /var/run as a symlink is difficult, because at times it is in .usr/share/factory/var/run (during build) and then it is in /var/run (at runtime). So a relative symlink is not possible. But an absolute symlink is not possible either, because we are installing out-of-tree. Oh the joys of cross-compilation... :-) We fix all this mess by making /var a real directory from the onset, so that we can use the runtime-expected layout even during the build. Then, during filesystem generation, we move /var away to the factory, and populate it as we used to do. This still requires a post-fs hook to restore /var after the filesystem generation. This leaves a situation that, should the filesystem generation fails, /var will be left in an inconsistent state. But that is not worse than what we already had anyway. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Cc: Trent Piepho <tpiepho@impinj.com> Cc: Adam Duskett <aduskett@gmail.com> Cc: Romain Naour <romain.naour@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2018-03-04 18:06:16 +01:00
mkdir -p $(TARGET_DIR)/var
ln -s ../run $(TARGET_DIR)/var/run
$(SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW)
endef
$(eval $(generic-package))