diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index f64d6b48a6..b666a3585d 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -588,7 +588,7 @@ int mount_all(const char *dest, /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing when we are privileged) */ { "tmpfs", "/tmp", "tmpfs", "mode=01777" NESTED_TMPFS_LIMITS, MS_NOSUID|MS_NODEV|MS_STRICTATIME, - MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR }, + MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR|MOUNT_USRQUOTA_GRACEFUL }, { "tmpfs", "/sys", "tmpfs", "mode=0555" TMPFS_LIMITS_SYS, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS|MOUNT_MKDIR|MOUNT_PRIVILEGED }, { "sysfs", "/sys", "sysfs", NULL, SYS_DEFAULT_MOUNT_FLAGS, @@ -598,7 +598,7 @@ int mount_all(const char *dest, { "tmpfs", "/dev", "tmpfs", "mode=0755" TMPFS_LIMITS_PRIVATE_DEV, MS_NOSUID|MS_STRICTATIME, MOUNT_FATAL|MOUNT_MKDIR }, { "tmpfs", "/dev/shm", "tmpfs", "mode=01777" NESTED_TMPFS_LIMITS, MS_NOSUID|MS_NODEV|MS_STRICTATIME, - MOUNT_FATAL|MOUNT_MKDIR }, + MOUNT_FATAL|MOUNT_MKDIR|MOUNT_USRQUOTA_GRACEFUL }, { "tmpfs", "/run", "tmpfs", "mode=0755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL|MOUNT_MKDIR }, { "/run/host", "/run/host", NULL, NULL, MS_BIND, @@ -706,6 +706,23 @@ int mount_all(const char *dest, o = options; } + if (FLAGS_SET(m->mount_settings, MOUNT_USRQUOTA_GRACEFUL)) { + r = mount_option_supported(m->type, /* key= */ "usrquota", /* value= */ NULL); + if (r < 0) + log_warning_errno(r, "Failed to determine if '%s' supports 'usrquota', assuming it doesn't: %m", m->type); + else if (r == 0) + log_info("Kernel doesn't support 'usrquota' on '%s', not including in mount options for '%s'.", m->type, m->where); + else { + _cleanup_free_ char *joined = NULL; + + if (!strextend_with_separator(&joined, ",", o ?: POINTER_MAX, "usrquota")) + return log_oom(); + + free_and_replace(options, joined); + o = options; + } + } + if (FLAGS_SET(m->mount_settings, MOUNT_PREFIX_ROOT)) { /* Optionally prefix the mount source with the root dir. This is useful in bind * mounts to be created within the container image before we transition into it. Note diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 53aa993d6a..1f54b51625 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -21,6 +21,7 @@ typedef enum MountSettingsMask { MOUNT_PREFIX_ROOT = 1 << 10,/* if set, prefix the source path with the container's root directory */ MOUNT_FOLLOW_SYMLINKS = 1 << 11,/* if set, we'll follow symlinks for the mount target */ MOUNT_PRIVILEGED = 1 << 12,/* if set, we'll only mount this in the outer child if we are running in privileged mode */ + MOUNT_USRQUOTA_GRACEFUL = 1 << 13,/* if set, append "usrquota" to mount options if kernel tmpfs supports that */ } MountSettingsMask; typedef enum CustomMountType { diff --git a/src/shared/mount-setup.c b/src/shared/mount-setup.c index 73be3b5dce..db8c2b61d2 100644 --- a/src/shared/mount-setup.c +++ b/src/shared/mount-setup.c @@ -34,11 +34,12 @@ #include "virt.h" typedef enum MountMode { - MNT_NONE = 0, - MNT_FATAL = 1 << 0, - MNT_IN_CONTAINER = 1 << 1, - MNT_CHECK_WRITABLE = 1 << 2, - MNT_FOLLOW_SYMLINK = 1 << 3, + MNT_NONE = 0, + MNT_FATAL = 1 << 0, + MNT_IN_CONTAINER = 1 << 1, + MNT_CHECK_WRITABLE = 1 << 2, + MNT_FOLLOW_SYMLINK = 1 << 3, + MNT_USRQUOTA_GRACEFUL = 1 << 4, } MountMode; typedef struct MountPoint { @@ -92,7 +93,7 @@ static const MountPoint mount_table[] = { mac_smack_use, MNT_FATAL }, #endif { "tmpfs", "/dev/shm", "tmpfs", "mode=01777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, - NULL, MNT_FATAL|MNT_IN_CONTAINER }, + NULL, MNT_FATAL|MNT_IN_CONTAINER|MNT_USRQUOTA_GRACEFUL }, { "devpts", "/dev/pts", "devpts", "mode=" STRINGIFY(TTY_MODE) ",gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, NULL, MNT_IN_CONTAINER }, #if ENABLE_SMACK @@ -189,13 +190,29 @@ static int mount_one(const MountPoint *p, bool relabel) { else (void) mkdir_p(p->where, 0755); + _cleanup_free_ char *extend_options = NULL; + const char *o = p->options; + if (FLAGS_SET(p->mode, MNT_USRQUOTA_GRACEFUL)) { + r = mount_option_supported(p->type, "usrquota", /* value= */ NULL); + if (r < 0) + log_warning_errno(r, "Unable to determine whether %s supports 'usrquota' mount option, assuming not: %m", p->type); + else if (r == 0) + log_info("Not enabling 'usrquota' on '%s' as kernel lacks support for it.", p->where); + else { + if (!strextend_with_separator(&extend_options, ",", p->options ?: POINTER_MAX, "usrquota")) + return log_oom(); + + o = extend_options; + } + } + log_debug("Mounting %s to %s of type %s with options %s.", p->what, p->where, p->type, - strna(p->options)); + strna(o)); - r = mount_verbose_full(priority, p->what, p->where, p->type, p->flags, p->options, FLAGS_SET(p->mode, MNT_FOLLOW_SYMLINK)); + r = mount_verbose_full(priority, p->what, p->where, p->type, p->flags, o, FLAGS_SET(p->mode, MNT_FOLLOW_SYMLINK)); if (r < 0) return FLAGS_SET(p->mode, MNT_FATAL) ? r : 0; diff --git a/units/tmp.mount b/units/tmp.mount index 896040524a..66ce92ad01 100644 --- a/units/tmp.mount +++ b/units/tmp.mount @@ -23,3 +23,4 @@ What=tmpfs Where=/tmp Type=tmpfs Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m +GracefulOptions=usrquota