diff mbox series

[2/7] system: add overlayfs option for ro /var

Message ID 20230115125253.280257-3-nolange79@gmail.com
State Superseded
Headers show
Series Extent options for read-only /var handling | expand

Commit Message

Norbert Lange Jan. 15, 2023, 12:52 p.m. UTC
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@.service.

2.  Mount an tmpfs and prepare the overlay at /run/.br/ovl/var

    This is done by using the template br-overlay-prepare@.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@free.fr>
Cc: Romain Naour <romain.naour@smile.fr>
Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
Signed-off-by: Norbert Lange <nolange79@gmail.com>
---
 .../overlayfs/br-bindmount-run@.service       | 26 +++++++++++++++++++
 .../overlayfs/br-overlay-prepare@.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@.service
 create mode 100644 package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
 create mode 100644 package/skeleton-init-systemd/overlayfs/overlay.mount.in

Comments

Arnout Vandecappelle Oct. 8, 2023, 6:37 p.m. UTC | #1
Hi Norbert,

On 15/01/2023 13:52, Norbert Lange wrote:
> 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.

[snip]
> 
> Cc: Yann E. MORIN <yann.morin.1998@free.fr>
> Cc: Romain Naour <romain.naour@smile.fr>
> Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
> Signed-off-by: Norbert Lange <nolange79@gmail.com>

  In the end, I ended up applying Yann's v4 instead, with a few more 
modifications, as reported in that thread. I did take inspiration from this 
patch - mostly from the commit message.

  For your information, I'll give some feedback on this patch as well.

> ---
>   .../overlayfs/br-bindmount-run@.service       | 26 +++++++++++++++++++
>   .../overlayfs/br-overlay-prepare@.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@.service
>   create mode 100644 package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
>   create mode 100644 package/skeleton-init-systemd/overlayfs/overlay.mount.in
> 
> diff --git a/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service
> new file mode 100644
> index 0000000000..ce944efd92
> --- /dev/null
> +++ b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.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

  There's no reason to make it a hidden directory. Also, there is no reason to 
abbreviate the directory name so much.

> +ExecStartPre=/bin/mkdir -m700 -p /run/.br/bnd

  I don't see why it's useful to have a separate base directory for bind mounts. 
When you do a bind mount like this, it's always for a very specific purpose - 
not always for an overlay, but in any case, it makes more sense to mount on a 
mount point that is more related to the sepecific purpose.

  For the overlay case, it's very convenient to have everything that the overlay 
builds on next to each other, i.e. lower, upper, work.

> +
> +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@.service b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
> new file mode 100644
> index 0000000000..86b32900dd
> --- /dev/null
> +++ b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.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

  I'm not sure if there's a good reason to make this mode 700 instead of the 
default 755. If there is a good reason, I'd accept a patch that modifies the 
prepare-var-overlay.service that I ended up applying.

> +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}

  There is in fact no reason to mount anything here - /run is already a tmpfs 
with all the required properties. We can just reuse it.

> +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@

  There's too much @PATH@ here. I actually think we can completely avoid it by 
using %p or %P as appropriate everywhere.

  I think that that way, we can indeed reuse both the overlay.mount.in and 
prepare-var-overlay@.service for other overlays. I unfortunately didn't have 
time to implement and test that, so instead I committed it without the %p/%P and 
without a template service.

  If you end up implementing it as a template, please make sure to also include 
a runtime test for it, e.g. with /etc as the overlay. Or even better something 
deeper - for the test it could be something silly, like /usr/share.

> +
> +After=br-bindmount-run@@PATH@.service
> +Requires=br-bindmount-run@@PATH@.service
> +
> +After=br-overlay-prepare@@PATH@.service
> +BindsTo=br-overlay-prepare@@PATH@.service
> +
> +[Mount]
> +Type=overlay
> +What=br_ovl_@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,@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@.service \
> +		$(TARGET_DIR)/usr/lib/systemd/system/br-bindmount-run@.service
> +	$(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/br-overlay-prepare@.service \
> +		$(TARGET_DIR)/usr/lib/systemd/system/br-overlay-prepare@.service

  If it's templates, they can actually be installed independently of the 
BR2_INIT_SYSTEMD_VAR_OVERLAYFS option - maybe you want to use a factory for /var 
but an overlay for /etc...


  I've marked this patch as Superseded (because I took Yann's v4). The rest of 
the series I'll look at later.

  Regards,
  Arnout

> +	# /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@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
Norbert Lange Oct. 9, 2023, 12:16 p.m. UTC | #2
Am So., 8. Okt. 2023 um 20:37 Uhr schrieb Arnout Vandecappelle <arnout@mind.be>:
>
>   Hi Norbert,
>
> On 15/01/2023 13:52, Norbert Lange wrote:
> > 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.
>
> [snip]
> >
> > Cc: Yann E. MORIN <yann.morin.1998@free.fr>
> > Cc: Romain Naour <romain.naour@smile.fr>
> > Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
> > Signed-off-by: Norbert Lange <nolange79@gmail.com>
>
>   In the end, I ended up applying Yann's v4 instead, with a few more
> modifications, as reported in that thread. I did take inspiration from this
> patch - mostly from the commit message.
>
>   For your information, I'll give some feedback on this patch as well.

Happy that there finally is some movement, still its weird that after
a long back-and-forth
a modified version is committed before feedback.

>
> > ---
> >   .../overlayfs/br-bindmount-run@.service       | 26 +++++++++++++++++++
> >   .../overlayfs/br-overlay-prepare@.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@.service
> >   create mode 100644 package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
> >   create mode 100644 package/skeleton-init-systemd/overlayfs/overlay.mount.in
> >
> > diff --git a/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service
> > new file mode 100644
> > index 0000000000..ce944efd92
> > --- /dev/null
> > +++ b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.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
>
>   There's no reason to make it a hidden directory. Also, there is no reason to
> abbreviate the directory name so much.

should be short imho, to avoid running into path-length problems.
its a technical detail, hidden from users

>
> > +ExecStartPre=/bin/mkdir -m700 -p /run/.br/bnd
>
>   I don't see why it's useful to have a separate base directory for bind mounts.
> When you do a bind mount like this, it's always for a very specific purpose -
> not always for an overlay, but in any case, it makes more sense to mount on a
> mount point that is more related to the sepecific purpose.

Because /run/.br could be for anything else later, and /run/.br/bnd
should mirror
the filesystem root.

>
>   For the overlay case, it's very convenient to have everything that the overlay
> builds on next to each other, i.e. lower, upper, work.

Yeah, there was a reason for not doing that, had to do
with being able to re-use that system of generic mount templates,
ie.  /run/.br/bnd would always mirror a part of the fs root, without
changed hierarchies.

ie. you could either use a single mount / to /run/.br/bnd, or say /etc
to /run/.br/bnd/etc and
/var to /run/.br/bnd/var. It would not effect the overlay units.

>
> > +
> > +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

This got left out aswell:
ExecStopPost=-/bin/rmdir /run/.br/bnd/%I

Removing it, would allow new accesses to the filesystem
thats in progress of being lazily unmounted.

> > diff --git a/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
> > new file mode 100644
> > index 0000000000..86b32900dd
> > --- /dev/null
> > +++ b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.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
>
>   I'm not sure if there's a good reason to make this mode 700 instead of the
> default 755. If there is a good reason, I'd accept a patch that modifies the
> prepare-var-overlay.service that I ended up applying.

No one should access this directories directly, its being defensive

>
> > +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}
>
>   There is in fact no reason to mount anything here - /run is already a tmpfs
> with all the required properties. We can just reuse it.

Yes, problem is that the /run mount is limited in size, not configurable
(parameters are in systemd's sources) and
filling /var with stuff should never exhaust one of the most critical
filesystems.

>
> > +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@
>
>   There's too much @PATH@ here. I actually think we can completely avoid it by
> using %p or %P as appropriate everywhere.
>
>   I think that that way, we can indeed reuse both the overlay.mount.in and
> prepare-var-overlay@.service for other overlays. I unfortunately didn't have
> time to implement and test that, so instead I committed it without the %p/%P and
> without a template service.
>
>   If you end up implementing it as a template, please make sure to also include
> a runtime test for it, e.g. with /etc as the overlay. Or even better something
> deeper - for the test it could be something silly, like /usr/share.

Yeah, gonna rebase my stuff and pickup where I stopped long ago,
gonna take a while.

>
> > +
> > +After=br-bindmount-run@@PATH@.service
> > +Requires=br-bindmount-run@@PATH@.service
> > +
> > +After=br-overlay-prepare@@PATH@.service
> > +BindsTo=br-overlay-prepare@@PATH@.service
> > +
> > +[Mount]
> > +Type=overlay
> > +What=br_ovl_@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,@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@.service \
> > +             $(TARGET_DIR)/usr/lib/systemd/system/br-bindmount-run@.service
> > +     $(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/br-overlay-prepare@.service \
> > +             $(TARGET_DIR)/usr/lib/systemd/system/br-overlay-prepare@.service
>
>   If it's templates, they can actually be installed independently of the
> BR2_INIT_SYSTEMD_VAR_OVERLAYFS option - maybe you want to use a factory for /var
> but an overlay for /etc...

Sure, but not sure if it should be installed unconditionally. Easy to
just copy those files into a
rootfs-overlay.

>
>
>   I've marked this patch as Superseded (because I took Yann's v4). The rest of
> the series I'll look at later.

Ok

>
>   Regards,
>   Arnout
>

Regards,
Norbert
diff mbox series

Patch

diff --git a/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.service
new file mode 100644
index 0000000000..ce944efd92
--- /dev/null
+++ b/package/skeleton-init-systemd/overlayfs/br-bindmount-run@.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@.service b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.service
new file mode 100644
index 0000000000..86b32900dd
--- /dev/null
+++ b/package/skeleton-init-systemd/overlayfs/br-overlay-prepare@.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@.service
+Requires=br-bindmount-run@@PATH@.service
+
+After=br-overlay-prepare@@PATH@.service
+BindsTo=br-overlay-prepare@@PATH@.service
+
+[Mount]
+Type=overlay
+What=br_ovl_@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,@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@.service \
+		$(TARGET_DIR)/usr/lib/systemd/system/br-bindmount-run@.service
+	$(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/overlayfs/br-overlay-prepare@.service \
+		$(TARGET_DIR)/usr/lib/systemd/system/br-overlay-prepare@.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@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