[Buildroot] [PATCH 23/24 v2] system: make systemd work on a read-only rootfs
Romain Naour
romain.naour at gmail.com
Sun Jul 3 12:54:54 UTC 2016
Le 22/06/2016 à 21:07, Yann E. MORIN a écrit :
> 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 feautre to populate it with
^
s/feautre/feature/
> "factory" defaults.
>
> We obtain those factory defaults by redirecting /var to that location at
> build time, usign a symlink /var -> /usr/share/factory which is the
^
s/usign/using/
> 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 acces rights on files
^
s/acces/access/
> or directoris in /var, and that only happens while assemblig the
^ ^
s/directoris/directories/
s/assemblig/assembling/
> 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.
>
> Signed-off-by: "Yann E. MORIN" <yann.morin.1998 at free.fr>
>
Other than small typos highlighted by my mail client ;-)
Reviewed-by: Romain Naour <romain.naour at gmail.com>
Best regards,
Romain
> ---
> Note: I haven't seen any symlinks installed in the factory so far, but I
> haven't build a lot of packages yet... So, I'm not sure what to do with
> the symlinks, especially when a package install relative symlinks...
> ---
> package/skeleton-systemd/skeleton-systemd.mk | 51 ++++++++++++++++++++++++++--
> system/Config.in | 1 -
> 2 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/package/skeleton-systemd/skeleton-systemd.mk b/package/skeleton-systemd/skeleton-systemd.mk
> index b45bbde..c7c2e26 100644
> --- a/package/skeleton-systemd/skeleton-systemd.mk
> +++ b/package/skeleton-systemd/skeleton-systemd.mk
> @@ -36,12 +36,59 @@ ifeq ($(SKELETON_SYSTEM_LOCALTIME),)
> SKELETON_SYSTEM_LOCALTIME = Etc/UTC
> endif
>
> +ifeq ($(BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW),y)
> +
> +define SKELETON_SYSTEMD_ROOT_RW
> + echo "/dev/root / auto rw 0 1" >$(TARGET_DIR)/etc/fstab
> + mkdir -p $(TARGET_DIR)/var
> +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_SYSTEMD_ROOT_RO
> + mkdir -p $(TARGET_DIR)/etc/systemd/tmpfiles.d
> + mkdir -p $(TARGET_DIR)/usr/share/factory
> + ln -s usr/share/factory $(TARGET_DIR)/var
> + 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_SYSTEMD_VAR_PRE_FS
> + rm -f $(TARGET_DIR)/var
> + mkdir $(TARGET_DIR)/var
> + for i in $(TARGET_DIR)/usr/share/factory/*; do \
> + j="$${i##*/}"; \
> + if [ -L "$${i}" ]; then \
> + printf "L+! /var/%s - - - - %s\n" \
> + "$${j}" "../usr/share/factory/$${j}" \
> + || exit 1; \
> + else \
> + printf "C! /var/%s - - - -\n" "$${j}" \
> + || exit 1; \
> + fi; \
> + done >$(TARGET_DIR)/etc/systemd/tmpfiles.d/var-factory.conf
> +endef
> +SKELETON_SYSTEMD_FS_PRE_CMD_HOOKS += SKELETON_SYSTEMD_VAR_PRE_FS
> +
> +define SKELETON_SYSTEMD_VAR_POST_FS
> + rm -rf $(TARGET_DIR)/var
> + ln -s usr/share/factory $(TARGET_DIR)/var
> +endef
> +SKELETON_SYSTEMD_FS_POST_CMD_HOOKS += SKELETON_SYSTEMD_VAR_POST_FS
> +
> +endif
> +
> define SKELETON_SYSTEMD_INSTALL_TARGET_CMDS
> mkdir -p $(TARGET_DIR)/etc
> mkdir -p $(TARGET_DIR)/home
> mkdir -p $(TARGET_DIR)/srv
> - mkdir -p $(TARGET_DIR)/var
> - echo "/dev/root / auto rw 0 1" >$(TARGET_DIR)/etc/fstab
> + $(SKELETON_SYSTEMD_ROOT_RO)
> + $(SKELETON_SYSTEMD_ROOT_RW)
> ln -sf ../usr/share/zoneinfo/$(SKELETON_SYSTEMD_LOCALTIME) \
> $(TARGET_DIR)/etc/localtime
> $(SKELETON_SYSTEMD_RSYNC_NETWORK)
> diff --git a/system/Config.in b/system/Config.in
> index 07af2e0..32d6542 100644
> --- a/system/Config.in
> +++ b/system/Config.in
> @@ -129,7 +129,6 @@ config BR2_INIT_SYSTEMD
> depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_10
> select BR2_ROOTFS_MERGED_USR
> select BR2_PACKAGE_SYSTEMD
> - select BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW
> select BR2_TARGET_TZ_INFO
>
> comment "systemd needs (e)glibc toolchain, headers >= 3.10"
>
More information about the buildroot
mailing list