[Buildroot] [PATCH 2/7] system: add overlayfs option for ro /var
Norbert Lange
nolange79 at gmail.com
Sun Jan 15 12:52:47 UTC 2023
This commit adds an alternative that has the following characteristics:
- Dont depend on anything being available, except the
API File Systems [1].
As /var is meant to be available before normal and even some early
services are running.
- Be a clean drop-in, that can be trivially added / removed.
- Depend on overlayfs being available in the kernel.
- Units are supposed to be reusable for custom solutions.
Further, a few subdirectories are introduced, which hopefully can serve
as template for similar uses.
Buildroot owns /run/.br, bind mounts end up in /run/.br/bnd,
overlay directories in /run/.br/ovl.
The sequence is rather important, and the systemd mount units serve as
reliable "sequence point" (cant be replicated otherwise).
What we need to do is mount /var in its usable state, and block
units depending on this before we are finished.
This includes:
- Other mounts targeting a subdirectory in /var.
- Units using 'RequiresMountsFor' targeting /var or subdirectories.
Most notable `basic.target` which most units depend upon by default.
- Units that are (transitively) odered after one of the above.
As comparison, the /var factory introduces issues here, as
systemd-tmpfiles-setup.service will require all mounts to be finished
before, as well als journald running.
(That means /var will already be used while and before initialization).
The necessary steps are:
1. Bindmount /var to /run/.br/bnd/var
This is done by using the template br-bindmount-run at .service.
2. Mount an tmpfs and prepare the overlay at /run/.br/ovl/var
This is done by using the template br-overlay-prepare at .service,
the mounting command is separated so that users can further
customize the behaviour.
The choice of using a service seems more flexible, as the
mount units lack several options of the mount command.
As a gut feeling the fileystems mounted under /run should
not be accessible or propagate their mounts,
hence --make-private.
(Or you might not use a mount at all).
3. Finally mount the overlay with a normal mount unit
Dependencies on the template-instances of 1. and 2. will ensure
correct odering before.
By nature off being a systemd mount unit the remaining units
will be automatically order after this unit if necessary.
As example, consider using /dev/sdc1 as upper layer for var,
this can be archived by swapping out just the line executing
the mount itself:
[Service]
ExecStart=
ExecStart=/bin/mount --make-private -n /dev/sdc1 ${OVERLAY_DIR}
[1] - https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems/
Cc: Yann E. MORIN <yann.morin.1998 at free.fr>
Cc: Romain Naour <romain.naour at smile.fr>
Cc: Jérémy Rosen <jeremy.rosen at smile.fr>
Signed-off-by: Norbert Lange <nolange79 at gmail.com>
---
.../overlayfs/br-bindmount-run at .service | 26 +++++++++++++++++++
.../overlayfs/br-overlay-prepare at .service | 26 +++++++++++++++++++
.../overlayfs/overlay.mount.in | 16 ++++++++++++
.../skeleton-init-systemd.mk | 17 ++++++++++++
system/Config.in | 13 ++++++++++
5 files changed, 98 insertions(+)
create mode 100644 package/skeleton-init-systemd/overlayfs/br-bindmount-run at .service
create mode 100644 package/skeleton-init-systemd/overlayfs/br-overlay-prepare at .service
create mode 100644 package/skeleton-init-systemd/overlayfs/overlay.mount.in
diff --git a/package/skeleton-init-systemd/overlayfs/br-bindmount-run at .service b/package/skeleton-init-systemd/overlayfs/br-bindmount-run at .service
new file mode 100644
index 0000000000..ce944efd92
--- /dev/null
+++ b/package/skeleton-init-systemd/overlayfs/br-bindmount-run at .service
@@ -0,0 +1,26 @@
+[Unit]
+Description=Bind-mount rootfs directory (/%I) to /run
+Documentation=man:file-hierarchy(7)
+ConditionPathIsSymbolicLink=!/%I
+DefaultDependencies=no
+Conflicts=umount.target
+Before=umount.target
+
+# Needs to run after rootfs is properly mounted
+# and before regular mounts might interfere.
+After=systemd-remount-fs.service
+Before=local-fs-pre.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+# dont fail if common dirs already exist
+ExecStartPre=/bin/mkdir -m755 -p /run/.br
+ExecStartPre=/bin/mkdir -m700 -p /run/.br/bnd
+
+ExecStartPre=/bin/mkdir -m700 -p /run/.br/bnd/%I
+ExecStart=/bin/mount --make-private -n --bind -o ro /%I /run/.br/bnd/%I
+
+# lazy unmount, dont block shutdown under any circumstances
+ExecStop=/bin/umount -n -l /run/.br/bnd/%I
+ExecStopPost=-/bin/rmdir /run/.br/bnd/%I
diff --git a/package/skeleton-init-systemd/overlayfs/br-overlay-prepare at .service b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare at .service
new file mode 100644
index 0000000000..86b32900dd
--- /dev/null
+++ b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare at .service
@@ -0,0 +1,26 @@
+[Unit]
+Description=Mount and prepare tmpfs for overlay (/%I)
+Documentation=man:file-hierarchy(7)
+ConditionPathIsSymbolicLink=!/%I
+DefaultDependencies=no
+Conflicts=umount.target
+Before=local-fs.target umount.target
+# prepare for systemd mount units aswell
+RequiresMountsFor=/run/.br/ovl/%I
+
+[Service]
+Environment="OVERLAY_DIR=/run/.br/ovl/%I"
+Type=oneshot
+RemainAfterExit=yes
+# dont fail if common dirs already exist
+ExecStartPre=/bin/mkdir -m755 -p /run/.br
+ExecStartPre=/bin/mkdir -m700 -p /run/.br/ovl
+
+ExecStartPre=/bin/mkdir -m700 -p ${OVERLAY_DIR}
+# Create an override and edit this line for customization
+ExecStart=/bin/mount --make-private -n -t tmpfs tmpfs_br_ovl ${OVERLAY_DIR}
+ExecStartPost=/bin/mkdir -p ${OVERLAY_DIR}/up ${OVERLAY_DIR}/wd
+
+# lazy unmount, dont block shutdown under any circumstances
+ExecStop=/bin/umount -n -l ${OVERLAY_DIR}
+ExecStopPost=/bin/rmdir ${OVERLAY_DIR}
diff --git a/package/skeleton-init-systemd/overlayfs/overlay.mount.in b/package/skeleton-init-systemd/overlayfs/overlay.mount.in
new file mode 100644
index 0000000000..84f4d9ee47
--- /dev/null
+++ b/package/skeleton-init-systemd/overlayfs/overlay.mount.in
@@ -0,0 +1,16 @@
+[Unit]
+Description=Variable storage (/@PATH@)
+Documentation=man:file-hierarchy(7)
+ConditionPathIsSymbolicLink=!/@PATH@
+
+After=br-bindmount-run@@PATH at .service
+Requires=br-bindmount-run@@PATH at .service
+
+After=br-overlay-prepare@@PATH at .service
+BindsTo=br-overlay-prepare@@PATH at .service
+
+[Mount]
+Type=overlay
+What=br_ovl_ at PATH@
+Where=/@PATH@
+Options=redirect_dir=on,index=on,xino=on,lowerdir=/run/.br/bnd/@PATH@,upperdir=/run/.br/ovl/@PATH@/up,workdir=/run/.br/ovl/@PATH@/wd
diff --git a/package/skeleton-init-systemd/skeleton-init-systemd.mk b/package/skeleton-init-systemd/skeleton-init-systemd.mk
index fb15552f99..ad529cddf6 100644
--- a/package/skeleton-init-systemd/skeleton-init-systemd.mk
+++ b/package/skeleton-init-systemd/skeleton-init-systemd.mk
@@ -57,6 +57,23 @@ define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
endef
SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS += SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
endif # BR2_INIT_SYSTEMD_VAR_FACTORY
+
+ifeq ($(BR2_INIT_SYSTEMD_VAR_OVERLAYFS),y)
+define SKELETON_INIT_SYSTEMD_LINUX_CONFIG_FIXUPS
+ $(call KCONFIG_ENABLE_OPT,CONFIG_OVERLAY_FS)
+endef
+define SKELETON_INIT_SYSTEMD_POST_INSTALL_VAR_OVERLAYFS
+ sed 's, at PATH@,var,g' $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/overlay.mount.in >$(@D)/var.mount
+ $(INSTALL) -D -m 0644 $(@D)/var.mount $(TARGET_DIR)/usr/lib/systemd/system/var.mount
+ $(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/br-bindmount-run at .service \
+ $(TARGET_DIR)/usr/lib/systemd/system/br-bindmount-run at .service
+ $(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/br-overlay-prepare at .service \
+ $(TARGET_DIR)/usr/lib/systemd/system/br-overlay-prepare at .service
+ # /var mount gets pulled in automatically by basic.target
+endef
+SKELETON_INIT_SYSTEMD_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_SYSTEMD_POST_INSTALL_VAR_OVERLAYFS
+endif # BR2_INIT_SYSTEMD_VAR_OVERLAYFS
+
endif # BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW
ifeq ($(BR2_INIT_SYSTEMD_POPULATE_TMPFILES),y)
diff --git a/system/Config.in b/system/Config.in
index 87df031545..cdf383d0d4 100644
--- a/system/Config.in
+++ b/system/Config.in
@@ -187,6 +187,19 @@ config BR2_INIT_SYSTEMD_VAR_FACTORY
var.mount unit, that overrides the What and Type, and possibly
the Options and After, fields.
+config BR2_INIT_SYSTEMD_VAR_OVERLAYFS
+ bool "mount an overlayfs backed by a tmpfs"
+ help
+ Mount an overlayfs on /var, with the upper as a tmpfs.
+
+ You can customize the backing storage with an override, for
+ ecample create this file and add the content following:
+ /lib/systemd/system/br-overlay-prepare at var.service.d/mount.conf
+
+ [Service]
+ ExecStart=
+ ExecStart=/bin/mount --make-private -n /dev/sdc1 ${OVERLAY_DIR}
+
config BR2_INIT_SYSTEMD_VAR_NONE
bool "do nothing"
help
--
2.39.0
More information about the buildroot
mailing list