From ff6883ca0655ac8844cd783caf6a7d8815515ba3 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Wed, 9 Jul 2014 19:07:38 -0400 Subject: [PATCH] ostree-remount: mount a tmpfs on /var if necessary so /var is read-write /var needs to be read-write for a functioning system. Various systemd services will fail to start if /var is read-only. After we remount /var (or if we skip remounting /var because / is read-only), if /var is still readonly, mount a tmpfs file system on /var. While this isn't strictly part of ostree, keeping it here makes sense because it keeps twiddling around with the /var mount in one place for easier coordination and maintenance. This will likely need updating if systemd gains better support for a readonly root filesystem. https://bugzilla.gnome.org/show_bug.cgi?id=732979 --- src/switchroot/ostree-remount.c | 53 +++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/switchroot/ostree-remount.c b/src/switchroot/ostree-remount.c index 84d9359c..4af7eeb2 100644 --- a/src/switchroot/ostree-remount.c +++ b/src/switchroot/ostree-remount.c @@ -37,25 +37,58 @@ #include "ostree-mount-util.h" +static int +path_is_on_readonly_fs (char *path) +{ + struct statvfs stvfsbuf; + + if (statvfs (path, &stvfsbuf) == -1) + { + perrorv ("statvfs(%s): ", path); + exit (1); + } + + return (stvfsbuf.f_flag & ST_RDONLY) != 0; +} + +/* Having a writeable /var is necessary for full system functioning. + * If /var isn't writeable, we mount tmpfs over it. While this is + * somewhat outside of ostree's scope, having all /var twiddling + * in one place will make future maintenance easier. + */ +static void +maybe_mount_tmpfs_on_var (void) +{ + if (!path_is_on_readonly_fs ("/var")) + return; + + if (umount ("/var") < 0 && errno != EINVAL) + { + perror ("failed to unmount /var prior to mounting tmpfs, mounting over"); + } + + if (mount ("tmpfs", "/var", "tmpfs", 0, NULL) < 0) + { + perror ("failed to mount tmpfs on /var"); + exit (1); + } +} + int main(int argc, char *argv[]) { const char *remounts[] = { "/sysroot", "/etc", "/home", "/root", "/tmp", "/var", NULL }; struct stat stbuf; int i; - struct statvfs stvfsbuf; - if (statvfs ("/", &stvfsbuf) == -1) - { - perror ("statvfs(/): "); - exit (1); - } - - if (stvfsbuf.f_flag & ST_RDONLY) + if (path_is_on_readonly_fs ("/")) { /* If / isn't writable, don't do any remounts; we don't want * to clear the readonly flag in that case. */ + + maybe_mount_tmpfs_on_var (); + exit (0); } @@ -81,7 +114,9 @@ main(int argc, char *argv[]) } } } - + + maybe_mount_tmpfs_on_var (); + exit (0); }