Suspendieren mit Root auf USB

Suspendieren mit Root auf USB

Ich habe einen Laptop, auf dem Ubuntu 14.04 von einem Root-Dateisystem auf einem USB-Speicher läuft. Das funktioniert nicht gut, da ext4 nach dem Aufwachen aus dem Ruhezustand häufig versucht, in das Root-Dateisystem zu schreiben, bevor USB bereit ist.

Wenn dies geschieht, wird mir Folgendes im Kernel-Protokoll angezeigt. Beachten Sie, dass ich eine Reihe von E/A-Fehlern erhalte sda1und das USB-Speicherlaufwerk eine Sekunde später endlich vom Kernel erkannt wird.

[ 2826.517419] wlan0: associated
[ 2826.517452] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[ 2827.575371] EXT4-fs warning (device sda1): ext4_end_bio:317: I/O error -5 writing to inode 1733735 (offset 0 size 0 starting block 12629950)
[ 2827.575380] Buffer I/O error on device sda1, logical block 12629694
[ 2827.575400] EXT4-fs warning (device sda1): ext4_end_bio:317: I/O error -5 writing to inode 3148603 (offset 0 size 8192 starting block 12844470)
[ 2827.575404] Buffer I/O error on device sda1, logical block 12844212
[ 2827.575411] Buffer I/O error on device sda1, logical block 12844213
[ 2827.575448] EXT4-fs warning (device sda1): ext4_end_bio:317: I/O error -5 writing to inode 3015015 (offset 0 size 90112 starting block 6588832)
[ 2827.575453] Buffer I/O error on device sda1, logical block 6588576
[ 2827.575461] Buffer I/O error on device sda1, logical block 6588577
[ 2827.575465] Buffer I/O error on device sda1, logical block 6588578
[ 2827.575469] Buffer I/O error on device sda1, logical block 6588579
[ 2827.575473] Buffer I/O error on device sda1, logical block 6588580
[ 2827.575477] Buffer I/O error on device sda1, logical block 6588581
[ 2827.575481] Buffer I/O error on device sda1, logical block 6588582
[ 2828.857284] sd 0:0:0:0: [sda] No Caching mode page found
[ 2828.857293] sd 0:0:0:0: [sda] Assuming drive cache: write through

Außerhalb des Kernel-Logs ist zunächst kein sichtbarer Hinweis darauf zu sehen, dass das Problem ausgelöst wurde. Wenn ich Ubuntu jedoch über diesen Punkt hinaus laufen lasse, tritt im Dateisystem ein Fehler auf und das Dateisystem wechselt schließlich in den Nur-Lese-Modus. An diesem Punkt muss ich im Wiederherstellungsmodus neu starten und fsck.ext4manuell von einer Root-Shell aus starten, um das Dateisystem zu reparieren.

Gibt es eine Einstellung, die ich so ändern kann, dass der Zugriff auf das Root-Gerät nach dem Aufwachen aus dem Ruhezustand verzögert werden kann, bis das USB-Laufwerk bereit ist?

Antwort1

Der Grund, warum dieses Problem nur bei USB-Geräten und nicht bei anderen Geräten auftritt, ist eine Kombination aus zwei Faktoren:

  • Anders als andere Speichermedien ist der Betrieb von USB-Speichern auf Kernel-Threads angewiesen.
  • Beim Fortsetzen aus dem Suspend-Modus weckt der Kernel alle Threads gleichzeitig.

Dies führt dazu, dass es während der Wiederaufnahme zu einem Wettlauf zwischen dem USB-System kommt, das einerseits versucht, Medien und Syslog zu erkennen, und dem System, das andererseits versucht, Protokollnachrichten aus dem Ruhezustand und der Wiederaufnahme auf die Festplatte zu schreiben.

Wenn Syslog einen Schreibversuch unternimmt, bevor das USB-Gerät erkannt wurde, tritt bei ext4 ein Fehler auf, der aus irgendeinem Grund nicht sauber behandelt wird und letztendlich dazu führt, dass fsck im Dateisystem manuell ausgeführt werden muss.

Die Lösung, die ich gefunden habe, besteht darin, Kernel-Threads einen Vorsprung von 12 Sekunden zu geben, bevor andere Threads geweckt werden. Damit das funktioniert, musste ich folgende Änderungen am Kernel vornehmen:

--- linux-3.13.0/kernel/power/suspend.c.orig    2014-01-20 03:40:07.000000000 +0100
+++ linux-3.13.0/kernel/power/suspend.c 2014-08-04 00:57:43.847038640 +0200
@@ -299,6 +299,8 @@
        goto Resume_devices;
 }

+unsigned int resume_delay = 0;
+
 /**
  * suspend_finish - Clean up before finishing the suspend sequence.
  *
@@ -307,6 +309,15 @@
  */
 static void suspend_finish(void)
 {
+       if (resume_delay) {
+               /* Give kernel threads a head start, such that usb-storage
+                * can detect devices before syslog attempts to write log
+                * messages from the suspend code.
+                */
+               thaw_kernel_threads();
+               pr_debug("PM: Sleeping for %d milliseconds.\n", resume_delay);
+               msleep(resume_delay);
+       }
        suspend_thaw_processes();
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
--- linux-3.13.0/kernel/sysctl.c.orig   2014-08-04 08:11:26.000000000 +0200
+++ linux-3.13.0/kernel/sysctl.c        2014-08-03 23:27:23.796278219 +0200
@@ -277,8 +277,17 @@
 static int max_extfrag_threshold = 1000;
 #endif

+extern unsigned int resume_delay;
+
 static struct ctl_table kern_table[] = {
        {
+               .procname       = "resume_delay",
+               .data           = &resume_delay,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       {
                .procname       = "sched_child_runs_first",
                .data           = &sysctl_sched_child_runs_first,
                .maxlen         = sizeof(unsigned int),

verwandte Informationen