Linux 파일 시스템에서 간단한 파일 복사(또는 쓰기)로 인해 10초 이상의 대기 시간이 발생함

Linux 파일 시스템에서 간단한 파일 복사(또는 쓰기)로 인해 10초 이상의 대기 시간이 발생함

저는 회전하는 하드 드라이브에서 Linux를 실행하고 있습니다. WDC WD5000LPLX-7, "WD 블랙 모바일", 7200RPM.

나는 간단한 파일 복사(또는 쓰기)로 인해 fsync()가 10초 이상 지연되는 것을 발견했습니다. Linux에서 이를 피할 수 있는 방법이 있나요?아니요하드웨어를 교체하거나 cp명령을 변경[*]하시겠습니까? 아니면 이것을 피할 수 있는 다른 방법은 없는 걸까요?

[*] 피할 수만 있다면O_DIRECT를 사용하여 파일 쓰기.

fsync()란 무엇입니까?

https://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/

rename() + fsync()는 정전 시에도 안전하게 파일을 자동으로 업데이트하는 데 사용됩니다.

애플리케이션 개발자는 별도의 스레드를 사용하여 구성/상태 업데이트를 작성하여 쓰기에 시간이 걸릴 경우 사용자 인터페이스가 정지되지 않도록 하는 것이 좋습니다. (예를 참조하세요:그놈 쉘에서 동결). 그러나 이 제안은 사용자 파일을 저장할 때 덜 유용해 보입니다. 예를 들어 터미널의 편집기를 사용하여 한 번에 하나씩 파일을 편집하는 경우 vi my-file편집이 wq완료됩니다. 당연히 vi종료하기 전에 fsync()가 완료될 때까지 기다립니다. 당신은 다른 편집기를 사용하는 것을 선호할 수도 있지만, 당신의 편집기도 같은 일을 할 것이라고 확신합니다 :-).

테스트 설정

$ sudo -i
# lvcreate alan_dell_2016 -n test --extents 100%FREE
  Logical volume "test" created.
# ls -l /dev/alan_dell_2016/test
lrwxrwxrwx. 1 root root 7 Feb 18 13:34 /dev/alan_dell_2016/test -> ../dm-3

$ uname -r
4.20.3-200.fc29.x86_64

$ cat /sys/block/sda/queue/scheduler
mq-deadline [bfq] none
$ cat /sys/block/dm-3/queue/scheduler
none

CFQ I/O 스케줄러를 사용하여 gnome-shell 동결을 재현했습니다. CFQ다음 커널 버전에서는 사라질 것입니다어쨌든 현재 내 시스템은 BFQ를 사용하도록 구성되어 있습니다.

mq-deadline스케줄러 도 사용해 봤습니다 . 이러한 모든 I/O 스케줄러에 대해 fsync()가 10초 이상 지연되는 것을 확인했습니다. 내 커널은 CONFIG_BLK_WBT_MQ=y로 빌드되었습니다. (WBT는 데드라인 스케줄러에 적용되며 기본적으로 적용되지 않습니다 bfq.)

# mkfs.ext4 /dev/alan_dell_2016/test
mke2fs 1.44.3 (10-July-2018)
Creating filesystem with 2982912 4k blocks and 746304 inodes
Filesystem UUID: 736bee3c-f0eb-49ee-b5be-de56ef1f38d4
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

# mount /dev/alan_dell_2016/test /mnt
# cd /mnt
# df -h .
Filesystem                       Size  Used Avail Use% Mounted on
/dev/mapper/alan_dell_2016-test   12G   41M   11G   1% /mnt

테스트 실행

# dd if=/dev/zero of=writetest bs=1M count=5k conv=fsync & sleep 1; while true; do time sh -c 'echo 1 > latencytest; time sync latencytest; mv latencytest latencytest2'; sleep 1; killall -0 dd || break; done
[1] 17060

real    1m14.972s
user    0m0.001s
sys 0m0.000s

real    1m14.978s
user    0m0.005s
sys 0m0.002s
5120+0 records in
5120+0 records out
5368709120 bytes (5.4 GB, 5.0 GiB) copied, 75.9998 s, 70.6 MB/s
[1]+  Done                    dd if=/dev/zero of=writetest bs=1M count=5k conv=fsync
dd: no process found

# cp writetest copytest & sleep 3; while true; do time sh -c 'echo 1 > latencytest; time sync latencytest; mv latencytest latencytest2'; sleep 3; killall -0 cp || break; done
[1] 17397

real    0m59.479s
user    0m0.000s
sys 0m0.002s
[1]+  Done                    cp -i writetest copytest

real    0m59.504s
user    0m0.037s
sys 0m4.385s
cp: no process found

나는 이것이 파일 시스템 세부 사항과 관련이 있다고 생각합니다. 블록 장치 수준에서 동일한 작업을 수행하면 대기 시간이 훨씬 낮아집니다.

# cd / && umount /mnt
# dd if=/dev/zero of=/dev/alan_dell_2016/test bs=1M count=2000 conv=fsync &
[1] 6681
# dd if=/dev/zero of=/dev/alan_dell_2016/test oflag=sync bs=4096 count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.193815 s, 21.1 kB/s

답변1

이러한 지연은 파일 시스템에 따라 다릅니다. 다양한 파일 시스템에서 테스트를 실행했습니다. ext3둘 다 ext4약간의 "나쁜" 결과를 보여주었습니다. XFS, btrfs 및 bcachefs는 "그렇게 나쁘지 않습니다". 엄격한 통계를 수집하지는 않았지만 다음 섹션에 몇 가지 예시적인 숫자가 있습니다.

업데이트: 결과는 커널 버전에 따라 달라집니다. 일부 패치가 방금 승인되었으며 ext4이 문제와 매우 관련이 있는 것 같습니다. 응!

에서 테스트를 실행해 보았는데 v5.2-rc5-293-g001da3fd278f10초 이상의 지연이 발생하지 않았습니다. 때때로 그것에 가깝지만. 때로는 내 XFS/btrfs/bcachefs 결과보다 더 나쁠 수도 있는 것 같습니다.

면책 조항: 내 테스트는 그다지 과학적이지 않습니다 :-). 이번 업데이트에서는 "10초가 넘는 fsync() 대기 시간"을 기준으로 계속 재현할 수 있는지 확인했습니다. 그러나 기본 테스트는 커널 5.1.6-200.fc29이 아닌 커널 에서 수행되었습니다 v5.2-rc5. 첫 번째 테스트( )에서는 긴 지연만 재현할 수 있었고 writetest두 번째 테스트( copytest)에서는 재현할 수 없었습니다.

copytest나중에 Firefox와 .Firefox 버전 67.0.4(여러 확장 포함)를 모두 테스트해 보았습니다 . (커널은 상단에 패치가 있는 v5.2-rc5-293-g001da3fd278f와 동일하며 기준선은 5.1.11-200.fc29입니다.)

내 Firefox 테스트는 새 탭을 여는 것이었습니다 google.com. 기준선에는 수십 초의 지연이 있습니다. 이는 다음과 같습니다.가능한유사한 긴 fsync 지연과 관련됩니다. 그리고 나생각하다패치된 커널은 Firefox에서 이 10초 이상의 지연을 수정합니다.

그래서 이번 패치에 대한 기대가 큽니다!

즉, copytest10G 정도에 도달하면 마우스 커서를 포함한 전체 GUI의 응답성이 떨어지기 시작합니다. Alt+SysRQ+R을 사용하여 VT 전환을 허용하도록 강제했습니다. 몇 번의 VT 스위치를 앞뒤로 전환한 후 GUI가 충돌했습니다.

충돌에 대한 로그 메시지는 이 답변 끝에 첨부되어 있습니다. 어쩌면 GUI는 이런 강제를 좋아하지 않을 수도 있습니다. 아니면 그것가능한교환으로 인한 지연은 Wayland 컴포지터 및/또는 XWayland에서 다음과 같은 일부 경쟁 조건을 유발할 수 있습니다.알려진 오류어느 그놈 껍질"피하려고 노력 중":-(.

Ted T'so는 또한 ext4 로깅의 장기적인 변경에 대해 불평해 왔습니다. 따라서 아마도 미래의 어느 시점에는 ext4에 더 많은 개선이 있을 것입니다!


[패치 v2 2/3] jbd2: jbd2_inode 더티 범위 소개

현재, Journal_submit_inode_data_buffers() 및 Journal_finish_inode_data_buffers()는 모두 특정 로그 항목과 연관된 각 inode의 전체 주소 공간에서 작동합니다. 그 결과 더티 페이지를 지속적으로 추가하는 inode가 있는 경우 다시 기록된 모든 페이지가 기록될 때까지 기다리는 동안 무한한 시간 동안 Journal_finish_inode_data_buffers()에서 대기하게 될 수 있습니다.

이러한 작업 부하를 발생시키는 가장 간단한 방법은 전체 파일 시스템을 채울 때까지 /dev/zero에서 파일을 추가하는 것입니다. 이로 인해 Journal_finish_inode_data_buffers()가 dd 작업의 전체 기간 동안 대기하게 될 수 있습니다.

특정 트랜잭션과 관련된 각 inode의 더티 범위 범위를 결정하여 이 상황을 개선할 수 있습니다. 범위가 jbd2 내에 포함되고 구조의 수명 주기 및 잠금 규칙을 따르도록 jbd2_inode 구조를 통해 이를 수행합니다.

이를 통해 쓰기 저장을 제한하고 저널_submit_inode_data_buffers() 및 Journal_finish_inode_data_buffers()에서 주어진 구조 jdb2_inode의 더티 범위에 대해 각각 대기할 수 있으므로 문제의 inode가 여전히 연결되어 있는 경우 영원히 기다리지 않아도 됩니다.

(이전) 다른 파일 시스템의 결과

이 테스트는 bachefs 트리 버전 v4.20-297-g2252e4b79f8f(2019-02-14)에서 빌드된 커널을 사용하여 수행되었습니다.

위 업데이트의 면책조항도 참조하세요. v5.1.6에서는 모든 ext4 결과를 재현할 수 없습니다. 내 테스트 방법이 신뢰할 수 없거나 v5.1.6으로 업그레이드할 때 큰 변경 사항이 있었습니다.

ext4 bfq: writetest saw 15s, 30s.  copytest 10s, 40s.
ext4 mq-deadline: writetest saw 10s, 30s.  copytest 5s, 45s.

ext3 bfq: writetest saw 20s, 40s.  copytest ~0.2s, once saw 0.5s and 2s.
ext3 mq-deadline: writetest saw 50s.  copytest ~0.2s, very occasionally 1.5s.
ext3 mq-deadline, wbt disabled: writetest saw 10s, 40s.  copytest similar to the above.

ext2 bfq: writetest 0.1 - 0.9s.  copytest ~0.5s.
ext2 mq-deadline: writetest 0.2 - 0.6s.  copytest ~0.4s

xfs bfq: writetest 0.5 - 2s.  copytest 0.5 - 3.5s.
xfs mq-deadline: writetest 0.2s, some 0.5s.  copytest 0 - 3s.

bcachefs bfq: writetest 1.5 - 3s.
bcachefs mq-deadline: writetest 1 - 5s.

btrfs bfq: writetest 0.5-2s, copytest 1 - 2s.
btrfs mq-deadline: writetest ~0.4s, copytest 1 - 4s.

파일을 복사할 때 ext3의 숫자가 더 좋아 보이지만 ext3은아니요일반적으로 말하면 연기하는 것이 좋습니다(예: tytso 링크 참조:-). ext2에 로그인 부족 - 일반적으로 견고성을 위해 로깅이 바람직하지만, ext 로깅이 이러한 지연의 원인입니다.

따라서 제가 가장 관심을 갖는 대안은 XFS, 실험적인 bachefs 및 btrfs입니다. 나는 XFS가 적어도 기계식 하드 드라이브에서는 사용하기 가장 쉽다고 생각합니다. 주목할만한 차이점 중 하나는 XFS 파일 시스템을 축소하는 도구가 없고 확장만 가능하다는 것입니다.

GUI 충돌

위의 "GUI 충돌"에 해당하는 로그 메시지입니다.

(이 충돌 직후 gdm 인사말 프로그램도 충돌했습니다. 하지만 메시지는 약간 달랐습니다.)

Jun 26 22:27:25 alan-laptop gnome-shell[1814]: Failed to set CRTC mode 1366x768: Permission denied
Jun 26 22:27:25 alan-laptop gnome-shell[1814]: Failed to disable CRTC
Jun 26 22:27:25 alan-laptop gnome-shell[1814]: Failed to disable CRTC
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: unknown object (31), message get_swipe_gesture(no)
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: error in client communication (pid 2259)
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: unknown object (28), message get_swipe_gesture(no)
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: error in client communication (pid 1896)
Jun 26 22:27:27 alan-laptop org.gnome.Shell.desktop[1814]: (EE)
Jun 26 22:27:27 alan-laptop org.gnome.Shell.desktop[1814]: Fatal server error:
Jun 26 22:27:27 alan-laptop org.gnome.Shell.desktop[1814]: (EE) wl_display@1: error 1: invalid arguments for [email protected]_relative_pointer
Jun 26 22:27:27 alan-laptop org.gnome.Shell.desktop[1814]: (EE)
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: unknown object (28), message get_swipe_gesture(no)
Jun 26 22:27:26 alan-laptop gnome-shell[1814]: WL: error in client communication (pid 2257)
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: WL: unknown object (237), message get_relative_pointer(no)
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: WL: error in client communication (pid 1814)
Jun 26 22:27:28 alan-laptop audit[1842]: ANOM_ABEND auid=1000 uid=1000 gid=1000 ses=2 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 pid=1842 comm="Xwayland" exe="/usr/bin/Xwayland" sig=6 res=1
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: clutter_actor_set_reactive: assertion 'CLUTTER_IS_ACTOR (actor)' failed
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: clutter_actor_set_reactive: assertion 'CLUTTER_IS_ACTOR (actor)' failed
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: clutter_actor_set_reactive: assertion 'CLUTTER_IS_ACTOR (actor)' failed
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: WL: unknown object (28), message get_swipe_gesture(no)
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: WL: error in client communication (pid 2251)
Jun 26 22:27:27 alan-laptop unknown[2257]: Error 22 (Invalid argument) dispatching to Wayland display.
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: clutter_input_device_get_device_type: assertion 'CLUTTER_IS_INPUT_DEVICE (device)' failed
Jun 26 22:27:27 alan-laptop gnome-shell[1814]: JS ERROR: TypeError: device is null
                                               _init/<@resource:///org/gnome/shell/ui/keyboard.js:615:1
Jun 26 22:27:27 alan-laptop unknown[2251]: Error 22 (Invalid argument) dispatching to Wayland display.
Jun 26 22:27:31 alan-laptop systemd[1]: Created slice system-systemd\x2dcoredump.slice.

관련 정보