USB에서 루트로 일시중단

USB에서 루트로 일시중단

USB 저장소의 루트 파일 시스템에서 Ubuntu 14.04를 실행하는 노트북이 있습니다. 일시 중지 상태에서 깨어난 후 USB가 준비되기 전에 ext4가 루트 파일 시스템에 쓰기를 자주 시도하기 때문에 이는 제대로 작동하지 않습니다.

이런 일이 발생하면 커널 로그에 표시되는 내용은 다음과 같습니다. 에서 여러 I/O 오류가 발생 sda1하고 1초 후에 USB 저장 드라이브가 마침내 커널에 의해 감지됩니다.

[ 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

처음에는 커널 로그 외부에 문제가 발생했다는 눈에 띄는 표시가 없지만, 이 지점 이후에도 Ubuntu를 계속 실행하면 파일 시스템에 오류가 발생하고 결국 읽기 전용 모드로 전환됩니다. 이 시점에서 fsck.ext4파일 시스템을 복구하려면 복구 모드로 재부팅하고 루트 셸에서 수동으로 실행해야 합니다 .

USB 드라이브가 준비될 때까지 일시 중지 상태에서 깨어난 후 루트 장치에 대한 액세스가 지연될 수 있도록 변경할 수 있는 몇 가지 설정이 있습니까?

답변1

이 문제가 USB 장치에서만 나타나고 다른 장치에서는 나타나지 않는 이유는 두 가지 요인이 결합되어 있기 때문입니다.

  • USB 저장소는 다른 저장 매체와 달리 커널 스레드에 의존하여 작동합니다.
  • 일시 중지 상태에서 다시 시작하면 커널은 모든 스레드를 동시에 깨웁니다.

결과적으로 다시 시작하는 동안 미디어를 감지하려고 하는 USB 시스템과 일시 중지 및 다시 시작에서 디스크에 로그 메시지를 쓰려고 하는 syslog 사이에 경쟁이 발생하게 됩니다.

USB 장치가 감지되기 ​​전에 syslog가 쓰기를 시도하면 ext4에 오류가 발생하며 어떤 이유로든 깔끔하게 처리되지 않고 결국 파일 시스템에서 fsck를 수동으로 실행해야 합니다.

내가 찾은 해결책은 다른 스레드가 깨어나기 전에 커널 스레드에 12초 먼저 시작하도록 하는 것이었습니다. 이것이 작동하기 위해 커널에 적용해야 했던 변경 사항은 다음과 같습니다.

--- 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),

관련 정보