873459, 878093

This commit is contained in:
Lennart Poettering 2012-11-20 19:58:53 +01:00
parent 59081b0084
commit 46f2542535
4 changed files with 243 additions and 6 deletions

View File

@ -0,0 +1,49 @@
From 0049f05a8bb82c3e084bacc5945596761d706c55 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 16 Nov 2012 01:30:29 +0100
Subject: [PATCH] shutdown: readd explicit sync() when shutting down
As it turns out reboot() doesn't actually imply a file system sync, but
only a disk sync. Accordingly, readd explicit sync() invocations
immediately before we invoke reboot().
This is much less dramatic than it might sounds as we umount all
disks/read-only remount them anyway before going down.
---
src/core/service.c | 1 +
src/core/shutdown.c | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/src/core/service.c b/src/core/service.c
index cf08485..df72aba 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2485,6 +2485,7 @@ static int service_start_limit_test(Service *s) {
case SERVICE_START_LIMIT_REBOOT_IMMEDIATE:
log_warning("%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id);
+ sync();
reboot(RB_AUTOBOOT);
break;
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index cc8c57b..b59aef1 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -273,6 +273,13 @@ int main(int argc, char *argv[]) {
}
}
+ /* The kernel will automaticall flush ATA disks and suchlike
+ * on reboot(), but the file systems need to be synce'd
+ * explicitly in advance. So let's do this here, but not
+ * needlessly slow down containers. */
+ if (!in_container)
+ sync();
+
if (cmd == LINUX_REBOOT_CMD_KEXEC) {
if (!in_container) {
--
1.7.12.1

View File

@ -0,0 +1,81 @@
From 891a4918ef75fa81e22691156c050d061bd53dd3 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 16 Nov 2012 18:15:30 +0100
Subject: [PATCH] switch-root: try pivot_root() before overmounting /
We should always try to umount the old root dir if possible, instead of
overmounting it -- if that's possible.
The initial ("first") kernel rootfs can never be umounted, hence
for the usual nitrd case we never bothered using pivot_root() and
hence with fully unmounting it. However, fedup now tranisitions twice
during boot, and in that case it is highly desirable that the "second"
root dir is entirely unmounted when we switch to the "third". This patch
makes that possible.
The pivot_root() needs a directory in the "third" root dir, to move the
"second" root dir to. We use /mnt for that, under the assumption that
this directory is likely to exist, and is not itself a mount point.
---
src/core/switch-root.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/core/switch-root.c b/src/core/switch-root.c
index 150332a..ce0e41d 100644
--- a/src/core/switch-root.c
+++ b/src/core/switch-root.c
@@ -30,6 +30,7 @@
#include "util.h"
#include "path-util.h"
#include "switch-root.h"
+#include "missing.h"
int switch_root(const char *new_root) {
@@ -44,10 +45,21 @@ int switch_root(const char *new_root) {
struct stat new_root_stat;
bool old_root_remove;
const char *i;
+ _cleanup_free_ char *temporary_old_root = NULL;
if (path_equal(new_root, "/"))
return 0;
+ /* When using pivot_root() we assume that /mnt exists as place
+ * we can temporarily move the old root to. As we immediately
+ * unmount it from there it doesn't matter much which
+ * directory we choose for this, but it should be more likely
+ * than not that /mnt exists and is suitable as mount point
+ * and is on the same fs as the old root dir */
+ temporary_old_root = strappend(new_root, "/mnt");
+ if (!temporary_old_root)
+ return -ENOMEM;
+
old_root_remove = in_initrd();
if (stat(new_root, &new_root_stat) < 0) {
@@ -103,7 +115,20 @@ int switch_root(const char *new_root) {
log_warning("Failed to open root directory: %m");
}
- if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) {
+ /* We first try a pivot_root() so that we can umount the old
+ * root dir. In many cases (i.e. where rootfs is /), that's
+ * not possible however, and hence we simply overmount root */
+ if (pivot_root(new_root, temporary_old_root) >= 0) {
+
+ /* Immediately get rid of the old root. Since we are
+ * running off it we need to do this lazily. */
+ if (umount2(temporary_old_root, MNT_DETACH) < 0) {
+ r = -errno;
+ log_error("Failed to umount old root dir %s: %m", temporary_old_root);
+ goto fail;
+ }
+
+ } else if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) {
r = -errno;
log_error("Failed to mount moving %s to /: %m", new_root);
goto fail;
--
1.7.12.1

View File

@ -0,0 +1,95 @@
From 93bd157722c76b47d80742f290373c1ce2865070 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 16 Nov 2012 18:36:28 +0100
Subject: [PATCH] umount: always remount read-only before unmounting in final
shutdown loop
---
src/core/umount.c | 57 ++++++++++++++++++++++++++-----------------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/src/core/umount.c b/src/core/umount.c
index 83c9de3..e794057 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -407,6 +407,33 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
assert(head);
LIST_FOREACH_SAFE(mount_point, m, n, *head) {
+
+ /* If we are in a container, don't attempt to
+ read-only mount anything as that brings no real
+ benefits, but might confuse the host, as we remount
+ the superblock here, not the bind mound. */
+ if (detect_container(NULL) <= 0) {
+ /* We always try to remount directories
+ * read-only first, before we go on and umount
+ * them.
+ *
+ * Mount points can be stacked. If a mount
+ * point is stacked below / or /usr, we
+ * cannnot umount or remount it directly,
+ * since there is no way to refer to the
+ * underlying mount. There's nothing we can do
+ * about it for the general case, but we can
+ * do something about it if it is aliased
+ * somehwere else via a bind mount. If we
+ * explicitly remount the super block of that
+ * alias read-only we hence should be
+ * relatively safe regarding keeping the fs we
+ * can otherwise not see dirty. */
+ mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+ }
+
+ /* Skip / and /usr since we cannot unmount that
+ * anyway, since we are running from it */
if (path_equal(m->path, "/")
#ifndef HAVE_SPLIT_USR
|| path_equal(m->path, "/usr")
@@ -432,29 +459,6 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
return n_failed;
}
-static int mount_points_list_remount_read_only(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0;
-
- assert(head);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
-
- /* Trying to remount read-only */
- if (mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL) == 0) {
- if (changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not remount as read-only %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
static int swap_points_list_off(MountPoint **head, bool *changed) {
MountPoint *m, *n;
int n_failed = 0;
@@ -571,13 +575,6 @@ int umount_all(bool *changed) {
if (r <= 0)
goto end;
- /* If we are in a container, don't attempt to read-only mount
- anything as that brings no real benefits, but might confuse
- the host, as we remount the superblock here, not the bind
- mound. */
- if (detect_container(NULL) <= 0)
- r = mount_points_list_remount_read_only(&mp_list_head, changed);
-
end:
mount_points_list_free(&mp_list_head);
--
1.7.12.1

View File

@ -22,7 +22,7 @@ Url: http://www.freedesktop.org/wiki/Software/systemd
# THIS PACKAGE FOR A NON-RAWHIDE DEVELOPMENT DISTRIBUTION! # THIS PACKAGE FOR A NON-RAWHIDE DEVELOPMENT DISTRIBUTION!
Version: 195 Version: 195
Release: 7%{?gitcommit:.git%{gitcommit}}%{?dist} Release: 8%{?gitcommit:.git%{gitcommit}}%{?dist}
# For a breakdown of the licensing, see README # For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+ License: LGPLv2+ and MIT and GPLv2+
Summary: A System and Service Manager Summary: A System and Service Manager
@ -91,6 +91,11 @@ Patch0: disable-broken-test-build.patch
# F18Beta blocker workaround: https://bugzilla.redhat.com/show_bug.cgi?id=873576 # F18Beta blocker workaround: https://bugzilla.redhat.com/show_bug.cgi?id=873576
Patch1: 0001-revert-udev-killing.patch Patch1: 0001-revert-udev-killing.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=873459
Patch2: 0001-shutdown-readd-explicit-sync-when-shutting-down.patch
Patch3: 0001-umount-always-remount-read-only-before-unmounting-in.patch
Patch4: 0001-switch-root-try-pivot_root-before-overmounting.patch
Obsoletes: SysVinit < 2.86-24, sysvinit < 2.86-24 Obsoletes: SysVinit < 2.86-24, sysvinit < 2.86-24
Provides: SysVinit = 2.86-24, sysvinit = 2.86-24 Provides: SysVinit = 2.86-24, sysvinit = 2.86-24
Provides: sysvinit-userspace Provides: sysvinit-userspace
@ -199,6 +204,9 @@ glib-based applications using libudev functionality.
%setup -q %{?gitcommit:-n %{name}-git%{gitcommit}} %setup -q %{?gitcommit:-n %{name}-git%{gitcommit}}
%patch0 -p1 %patch0 -p1
%patch1 -p1 %patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%build %build
%{?gitcommit: ./autogen.sh } %{?gitcommit: ./autogen.sh }
@ -418,7 +426,7 @@ if [ -e /etc/sysconfig/i18n -a ! -e /etc/locale.conf ]; then
unset LC_TELEPHONE unset LC_TELEPHONE
unset LC_MEASUREMENT unset LC_MEASUREMENT
unset LC_IDENTIFICATION unset LC_IDENTIFICATION
. /etc/sysconfig/i18n 2>&1 || : . /etc/sysconfig/i18n >/dev/null 2>&1 || :
[ -n "$LANG" ] && echo LANG=$LANG > /etc/locale.conf 2>&1 || : [ -n "$LANG" ] && echo LANG=$LANG > /etc/locale.conf 2>&1 || :
[ -n "$LC_CTYPE" ] && echo LC_CTYPE=$LC_CTYPE >> /etc/locale.conf 2>&1 || : [ -n "$LC_CTYPE" ] && echo LC_CTYPE=$LC_CTYPE >> /etc/locale.conf 2>&1 || :
[ -n "$LC_NUMERIC" ] && echo LC_NUMERIC=$LC_NUMERIC >> /etc/locale.conf 2>&1 || : [ -n "$LC_NUMERIC" ] && echo LC_NUMERIC=$LC_NUMERIC >> /etc/locale.conf 2>&1 || :
@ -440,8 +448,8 @@ if [ -e /etc/sysconfig/keyboard -a ! -e /etc/vconsole.conf ]; then
unset SYSFONTACM unset SYSFONTACM
unset UNIMAP unset UNIMAP
unset KEYMAP unset KEYMAP
[ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n 2>&1 || : [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n >/dev/null 2>&1 || :
. /etc/sysconfig/keyboard 2>&1 || : . /etc/sysconfig/keyboard >/dev/null 2>&1 || :
[ -n "$SYSFONT" ] && echo FONT=$SYSFONT > /etc/vconsole.conf 2>&1 || : [ -n "$SYSFONT" ] && echo FONT=$SYSFONT > /etc/vconsole.conf 2>&1 || :
[ -n "$SYSFONTACM" ] && echo FONT_MAP=$SYSFONTACM >> /etc/vconsole.conf 2>&1 || : [ -n "$SYSFONTACM" ] && echo FONT_MAP=$SYSFONTACM >> /etc/vconsole.conf 2>&1 || :
[ -n "$UNIMAP" ] && echo FONT_UNIMAP=$UNIMAP >> /etc/vconsole.conf 2>&1 || : [ -n "$UNIMAP" ] && echo FONT_UNIMAP=$UNIMAP >> /etc/vconsole.conf 2>&1 || :
@ -453,10 +461,10 @@ fi
# Migrate HOSTNAME= from /etc/sysconfig/network # Migrate HOSTNAME= from /etc/sysconfig/network
if [ -e /etc/sysconfig/network -a ! -e /etc/hostname ]; then if [ -e /etc/sysconfig/network -a ! -e /etc/hostname ]; then
unset HOSTNAME unset HOSTNAME
. /etc/sysconfig/network 2>&1 || : . /etc/sysconfig/network >/dev/null 2>&1 || :
[ -n "$HOSTNAME" ] && echo $HOSTNAME > /etc/hostname 2>&1 || : [ -n "$HOSTNAME" ] && echo $HOSTNAME > /etc/hostname 2>&1 || :
fi fi
/usr/bin/sed -i '/^HOSTNAME=/d' /etc/sysconfig/network 2>&1 || : /usr/bin/sed -i '/^HOSTNAME=/d' /etc/sysconfig/network >/dev/null 2>&1 || :
%posttrans %posttrans
# Convert old /etc/sysconfig/desktop settings # Convert old /etc/sysconfig/desktop settings
@ -710,6 +718,10 @@ fi
%{_libdir}/pkgconfig/gudev-1.0* %{_libdir}/pkgconfig/gudev-1.0*
%changelog %changelog
* Tue Nov 20 2012 Lennart Poettering <lpoetter@redhat.com> - 195-8
- https://bugzilla.redhat.com/show_bug.cgi?id=873459
- https://bugzilla.redhat.com/show_bug.cgi?id=878093
* Thu Nov 15 2012 Michal Schmidt <mschmidt@redhat.com> - 195-7 * Thu Nov 15 2012 Michal Schmidt <mschmidt@redhat.com> - 195-7
- Revert udev killing cgroup patch for F18 Beta. - Revert udev killing cgroup patch for F18 Beta.
- https://bugzilla.redhat.com/show_bug.cgi?id=873576 - https://bugzilla.redhat.com/show_bug.cgi?id=873576