본문 바로가기

Linux Kernel

[LWN.net] bdflush() 시스템 호출의 삭제

반응형

 

 

Bye-bye bdflush() [LWN.net]

Did you know...?LWN.net is a subscriber-supported publication; we rely on subscribers to keep the entire operation going. Please help out by buying a subscription and keeping LWN on the net. By Jonathan Corbet July 5, 2021 The addition of system calls to t

lwn.net

리눅스 커널에는 종종 시스템 호출이 추가된다. 거의 모든 merge window마다 시스템 호출이 추가된다. 하지만 시스템 호출이 제거되는 경우는 훨씬 적다. 근데 이제 시스템 호출 하나가 없어지게 생겼는데, 바로 bdflush다.

https://man7.org/linux/man-pages/man2/bdflush.2.html

리눅스는 파일시스템 IO를 바로바로 처리하는게 아니라, 버퍼에 담아두었다가 한꺼번에 처리한다. 다시 말해 write()를 호출하면, 바로 디스크에 기록되는게 아니라 page cache에 기록되었다가 나중에 디스크에 기록된다. 최적화를 한 것이다.

 

하지만 버퍼에 영원히 데이터를 담아둘 수는 없다. 언젠가는 운영체제가 버퍼를 비우고 디스크에 기록해야한다. 리눅스의 완전 초반인 0.01 버전에서도 sync()라는 함수가 버퍼를 비우는 역할을 담당했다. 근데 sync()는 결국 사용자가 호출해야 하므로, 주기적으로 메모리 안의 데이터와 디스크가 동기화된다는 보장이 되지 않는다.

 

이런 동기화 작업을 커널에서 처리하면 장점이 있는데, 왜냐면 버퍼 캐시와 디바이스 자체를 커널이 관리하기 때문에 언제, 어떻게 비울지를 잘 알고있기 때문이다. 그래서 1994년 2월 2일, 0.99.14y 릴리즈에서는 bdflush()가 추가되었다. (이때는 지금과 완전 다른 페이스로 개발이 되었다.  0.99.14x 다음에 7시간만에 0.99.14y가 나오고, 또 9시간 만에 0.99.14z가 나왔다 ㄷㄷ)  근데 처음의 bdflush()는 기능은 없고 "not implemented" 오류를 띄우는 것 밖에 하지 않았다. 1.1.3이 되어서야 구현이 추가되었다.

 

근데 bdflush()라는 시스템 호출은 좀 이상하다.

int bdflush(int func, long data);

func = 0이면 리턴을 하지 않고, 커널 내부에서 루프를 돌면서 dirty buffer를 비워준다. 이때 버퍼를 비워주는 것은 사용자 공간의 프로세스이다. (이때는 커널 스레드라는 것도 존재하지 않았다.)

 

func = 1인 경우에는 일부 버퍼를 즉각적으로 비워준다. func의 1보다 크게 하면, 버퍼를 비우는 스레드로부터 제어와 관련된 파라미터를 읽거나 쓴다. 파라미터는 예를 들어서 버퍼를 비우기 위해서 몇퍼센트 이상의 버퍼가 dirty buffer이어야 하는지, 매 사이클마다 몇 개의 블록에 기록을 할 것인지 등등이다. (사실 번역하면서 뭐라는지 잘 모르겠다.)

 

또 bdflush()의 문제는 처음부터 bdflush()는 싱글 스레드로 구현이 되었다. 리눅스가 큰 시스템에서 인기를 끌면서, 싱글 스레드로 버퍼를 비우는 것이 엄청난 병목이 되었다. 그래서 Andrew Morton이 2002년에 2.5.8 커널에서 아예 다시 작성했다. 이때부터는 pdflush라는 커널 스레드가 각각의 물리적인 드라이브에 할당이 되면서 확장성이 좋아졌다.

 

그리고 2002년 10월에는, Robert Love가 bdflush() 시스템 호출을 deprecate하는 패치를 Andrew Morton이 merge했다. 그래서 "이 시스템 호출은 미래에 사라질 것"이라고 했다. 2009년(2.6.32)에 pdflush 스레드는 제거되고, 대신 워크 큐 기반으로 더 우아하게 작성되었다. 그래서 현재(2021)까지도 kworker/u8:3-flush-259:0 이라는 스레드가 그 역할을 담당한다. 하지만 bdflush()라는 시스템 호출은 별다른 역할도 없이 수년동안 유지되고 있다.

 

최근에 Eric Beiderman은 exit() 함수 관련 코드를 재작성하고 있는데, 그 일환으로 bdflush()를 아예 없애버리자고 제안했다. 애초에 bdflush()는 아무 기능도 하지 않으니까 지우자는 것이다.

 

bdflush()는 19년동안 deprecate되기도 했고, 알려진 사용자가 아무도 없다. 그래서 없애도 큰 문제는 되지 않을거다. 지금으로서는 bdflush()가 사라지면, 2019년에 사라진 sysctl() 이후로 두 번째로 사라지는 시스템 호출이 된다.

 

 

Bye-bye bdflush() [LWN.net]

Did you know...?LWN.net is a subscriber-supported publication; we rely on subscribers to keep the entire operation going. Please help out by buying a subscription and keeping LWN on the net. By Jonathan Corbet July 5, 2021 The addition of system calls to t

lwn.net