이번 주 LWN.net 위클리 에디션(9월 3일자) 주요 내용이다. Python 스티어링 카운슬이 JIT 컴파일러 개발을 PEP 승인 전까지 멈춰 세웠고, 그 결과 나온 PEP 836은 “이건 PEP 두 개여야 한다”는 지적에 발이 묶여 있다. 커널 쪽에서는 Rust로 다시 쓴 null 블록 드라이버 rnull이 C 버전과 기능 동등성에 도달해 앞으로 나올 블록 드라이버의 청사진 역할을 하게 됐고, 가상 머신이 스틸 타임을 보고 스스로 vCPU 수를 줄이는 steal governor 패치가 머지를 노리고 있다. 7.3 머지 윈도우는 15,267개 커밋으로 역대 두 번째 규모로 닫혔다. 여기에 LUKS 디스크 암호화 키가 절전 시 메모리에 남아있던 2년짜리 버그, GNOME의 RFC 프로세스 도입, LWN 구독료 인상까지 다룬다.
- A pause for the Python JIT — 6월부터 멈춰 선 CPython JIT 개발과 PEP 836 논쟁
- The “rnull” Rust block driver — Rust로 블록 드라이버를 쓰는 법을 보여주는 레퍼런스 구현
- Using steal time to moderate CPU demands — 경합이 심할 때 게스트가 자발적으로 vCPU를 반납하는 steal governor
- Governing GNOMEs — 개인 메인테이너 모델에서 팀·RFC 체제로 가는 GNOME
- The rest of the 7.3 merge window — sched_ext 서브 스케줄러 완성, ntfs3 대체 데이터 스트림, swap_ops 재작업
- Securely suspending LUKS-encrypted disks — 6.9부터 2년간 디스크 암호화 키가 지워지지 않던 리팩터링 회귀
- A note on subscription prices from LWN — 2022년 이후 첫 구독료 인상, 9월 15일부터 약 20%
- 짧은 소식: git.kernel.org 트래픽의 98%가 스크레이퍼, Debian의 생성형 AI 총회 투표 결과, sparse 메인테이너를 찾는 토발즈, Firefox 155, Incus 7.4, OpenShot 4.0
Python JIT 개발 중단과 PEP 836
Python 3.13(2024년)에 실험적 JIT 컴파일러가 들어간 이후 개발은 계속됐지만, 그 근거는 정보성(informational) PEP인 PEP 744뿐이었다. 정보성 PEP는 구속력이 없고 공식 합의를 뜻하지도 않는다. 애초에 Brandt Bucher가 JIT 추가 PR을 머지한 것이 2024년 1월이고, PEP 744가 나온 것은 그로부터 몇 달 뒤인 4월이다. 당시 3.13 릴리스 매니저였던 Thomas Wouters가 “왜 PEP 없이 기능이 들어갔느냐”고 물어서 뒤늦게 작성된 문서다.
지난 6월 스티어링 카운슬(SC)은 버그·보안 수정을 제외한 JIT 신규 개발을 main 브랜치에서 중단시켰다. JIT를 CPython의 정식 구성 요소로 인정할지 판단할 표준 트랙 PEP를 6개월 안에 제출·승인받지 못하면 JIT 코드를 main에서 들어내겠다는 조건도 붙였다. SC가 PEP에 요구한 항목은 장기 유지보수 계획, 다른 CPython 기능·툴링과의 호환성, 서드파티 JIT과의 관계, 아키텍처 안정성, 그리고 “명확하고 측정 가능한 성공 지표와 일정”이다.
SC는 이것이 JIT 작업에 대한 비판이 아니라고 못 박았다. “깊이 있는 기술 작업이었고 최근의 성능 개선은 실재하며 고무적이다”라는 것이다. 다만 프로젝트가 몇 차례 재설계를 거친 지금이 “JIT의 비공식적 지위를 재평가하기 좋은 시점”이라고 봤다. Wouters는 특정 사건이 계기가 된 것은 아니며 3.15 베타 이후에 발표한 것은 “3.15까지는 현상 유지를 받아들인다”는 신호였다고 설명했다.
반발의 초점은 개발을 멈춰 세운 방식이었다. Mark Shannon은 PEP 논의가 제대로 이뤄지도록 한두 달의 유예를 요청하면서 “PR은 썩고 다른 기여자는 흥미를 잃는다”고 우려했고, Alyssa Coghlan은 최소한 진행 중인 PR에는 유예가 필요하다며 “‘PEP 승인 전까지 새 PR 금지’와 ‘이미 진행 중인 변경의 골대를 옮기는 것’은 다른 이야기”라고 지적했다. SC 멤버들은 예외를 두기보다 그 기여자들을 PEP 작성 과정에 참여시키는 편이 낫다고 답했다.
7월 3일 Ken Jin이 발표한 PEP 836(“JIT Go Brrr”)은 JIT의 현재 상태와 2년 반짜리 로드맵을 담았다. 정식 기능 전환의 조건을 정해두는 대신, 기본 활성화 여부의 결정을 릴리스 매니저에게 맡긴 것이 특징이다. 현재 JIT는 Windows·macOS 바이너리와 일부 배포판(Fedora, Gentoo)에 포함돼 있지만 모두 기본 비활성화이며, PYTHON_JIT=1 환경변수로 켤 수 있다.
| 시점 | 목표 |
|---|---|
| 1년차 | 개발자 경험 개선, 프리스레드(no-GIL) Python 호환, 회귀 방지, 네이티브 프로파일러·디버거 테스트 추가 |
| 2년차 (3.17 첫 베타) | pyperformance 기준 프리스레드 단독 대비 기하평균 20% 이상 성능 향상 |
| 3.17 첫 RC | 주요 PyPI 패키지 테스트 스위트를 돌려 JIT 호환성 검토 |
PEP는 LLVM 버전 문제도 다룬다. 지금은 JIT를 켜고 Python을 빌드하려면 특정 LLVM 버전이 필요한데, 3.14는 LLVM 19, 3.15는 LLVM 21을 요구하고 두 버전 모두 이미 EOL이다. LLVM은 JIT가 쓰는 “스텐실(stencil)” 템플릿을 만드는 데 쓰인다. LLVM 의존성을 아예 없애는 별도의 표준 트랙 제안 PEP 774가 있지만 아직 승인되지 않았고, LTS 릴리스에서 Python을 오래 지원해야 하는 배포판에는 현재 상황이 실질적인 문제다.
프론트엔드 교체도 함께 제안됐다. 현재의 트레이스 기록(trace-recording) 프론트엔드를 메서드 단위 프론트엔드로 바꿔 유지보수를 쉽게 하고 “더 전통적이고 가르치기 쉽게” 만들자는 것이다. PEP는 그 이유로 “현재의 트레이싱 프론트엔드는 아주 단순한 벤치마크 프로그램에서도 고개를 갸웃하게 만드는 결과를 낸다”고 적었다.
논의에서 반복적으로 나온 지적은 “이건 PEP 두 개”라는 것이다. Wouters는 승인 기준을 정하는 문서와 그 기준을 어떻게 달성할지 설명하는 문서는 별개여야 한다고 봤고, PEP에 박힌 확정적 일정에도 “오픈소스 프로젝트, 특히 하위 호환성을 신경 쓰는 프로젝트의 개발 방식이 아니다”라고 했다. 그는 시작 시간·워밍업 시간·메모리 오버헤드를 명시적으로 다룰 것도 요구했다. 엄격한 수치일 필요는 없지만 추적하지 않으면 JIT를 켰을 때 치르는 비용을 알 수 없다는 논리다. CinderX 기여자 Kevin Newton은 더 근본적인 문제를 짚었다. PEP가 트레이싱 JIT와 메서드 단위 JIT의 차이를 과소평가하고 있으며, 단순함을 좇다 보면 “누군가의 머릿속에 들어가도록 만든, 가질 가치가 없는 JIT 컴파일러”가 나온다는 것이다.
반대편에서는 Eric Snow가 “계속되는 압박”에 반발하며, 설계 문서화는 가치 있지만 main 저장소에서의 개발 자체를 막는 것에는 동의하지 않는다고 했다. 잡무처럼 보이는 요구를 계속 늘리면 기여자가 떠나고 Python이 “주로 기업 팀만 참여하는 프로젝트”가 될 위험이 있다는 것이다. 8월 6일 SC 회의에서 저자들과 오피스 아워를 가졌다는 요약만 나왔을 뿐 결론은 공개되지 않았고, PEP를 쪼개겠다는 저자들의 약속도 아직 없다. JIT에 정면으로 반대하는 사람은 없지만, 개발은 사실상 멈춘 상태다.
rnull: Rust로 다시 쓴 null 블록 드라이버
null_blk은 모든 요청을 받아 최소한의 일만 하고 곧바로 완료 처리하는 작은 드라이버다. 6월에 Andreas Hindborg가 같은 기능을 Rust로 구현한 패치 세트를 올렸다. 최소 버전의 “rnull”은 이미 메인라인에 있고, 이번 패치 세트가 C 버전과 기능 동등성을 맞춘다. 목적은 null_blk을 대체하는 것이 아니라 “이제 Rust API로 간단한 블록 드라이버를 쓸 수 있다”는 것을 보이고 C 구현과 비교 가능한 기준점을 만드는 데 있다.
패치 세트의 대부분은 블록 드라이버를 쓰는 데 필요한 마지막 Rust 추상화를 채우는 코드다. 전체 흐름은 앞서 LWN이 다룬 AX88796B 네트워크 드라이버와 같지만, configfs 인터페이스 참조를 pinning으로 보관하기 때문에 모듈 초기화 함수가 복잡해진다. 초기화 본체는 pin_init_scope() 호출로 감싸는데, 이 함수는 메모리 초기화 방법을 기술한 코드 블록을 받아 초기화되지 않은 raw 메모리를 Rust 코드에 노출하지 않은 채 제자리에서 핀 고정(immovable) 객체를 만든다.
pin_init::pin_init_scope(move || -> Result<_, Error> {
// 모듈 파라미터를 읽는다
let blocking = module_parameters::blocking.value();
// 나머지 파라미터 생략
...
// 요청을 하드웨어 큐에 매핑하는 태그 세트를 만든다
let shared_tag_set = NullBlkDevice::build_tag_set(...);
// 디스크 생성
let mut disks = KVec::new();
for i in 0..module_parameters::nr_devices.value() {
...
let disk = NullBlkDevice::new(...)?;
disks.push(disk, GFP_KERNEL)?;
}
// 핀 고정된 모듈 데이터에 포인터를 저장한다
Ok(try_pin_init!(Self {
configfs_subsystem <- configfs::subsystem(shared_tag_set),
param_disks <- new_mutex!(disks),
}))
})각 블록 장치는 NullBlkDevice 구조체로 표현되고, 여기에 Operations 트레이트를 구현해 디스크 연산을 정의한다. #[vtable] 매크로가 트레이트의 함수들을 함수 포인터 구조체로 묶어주는데, 커널의 나머지 부분에서 보면 C 구현과 구별되지 않는 형태다. 요청 처리의 핵심인 queue_rq_internal()은 커널 C 코드의 struct request를 감싼 Request를 받아, 플러시 요청이면 메모리 백엔드를 비우고, 폴링 요청이면 폴 큐에 넣고, 나머지는 즉시 완료 처리한다.
configfs 쪽에서는 #[vtable]이 조금 다르게 쓰인다. 트레이트 하나를 vtable 하나로 만드는 대신, const 제네릭으로 구분되는 configfs 속성마다 vtable을 따로 생성한다. 아래 코드에서 impl 줄의 “12”가 이 구현을 열두 번째 configfs 속성과 묶는다. 단순한 설정은 configfs_simple_bool_field!() 같은 매크로로 보일러플레이트를 줄일 수 있지만, 에러 주입 대상 섹터를 지정하는 “badblocks”처럼 그렇게 줄일 수 없는 속성은 show()/store()를 직접 구현해야 한다.
#[vtable]
impl configfs::AttributeOperations<12> for DeviceConfig {
type Data = DeviceConfig;
fn show(this: &DeviceConfig, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
let ret = this.data.lock().bad_blocks.show(page, false);
if ret < 0 {
Err(Error::from_errno(ret as c_int))
} else {
Ok(ret as usize)
}
}
fn store(this: &DeviceConfig, page: &[u8]) -> Result {
for line in core::str::from_utf8(page)?.lines() {
// 각 줄을 파싱해 DeviceConfig에 설정을 반영한다
...
}
Ok(())
}
}모듈이 로드되면 Rust configfs 래퍼가 이 vtable들을 담은 configfs::Subsystem 구조체를 configfs에 자동 등록한다. 사용자가 아래처럼 장치를 만들어 활성화하면 configfs 코드가 C 쪽 struct gendisk에 대응하는 GenDisk 구조체를 만들고, 거기에 NullBlkDevice vtable 포인터를 저장한다.
mount -t configfs none /config
mkdir /config/rnull/<block_device_name>
echo 1 > /config/rnull/<block_device_name>/power성능은 어떨까. Rust for Linux 프로젝트 문서에 6.19-rc5 커널에서 두 드라이버를 비교한 벤치마크가 있는데, 결과는 단순하지 않다. 싱글스레드 성능과 큐 깊이가 높을 때의 성능은 약간 나쁘고, 일부 요청 크기에서는 오히려 낫고, 대부분의 구성에서는 통계적으로 구분되지 않는다.
덧붙이면, 기사 댓글에서 null_blk 원작자 Jens Axboe가 성격 규정을 바로잡았다. 처음에는 blk-mq와 I/O 스케줄링을 벤치마크하려고 만들었지만 “오늘날 주된 용도는 테스트용 설정 가능 블록 장치”이며, blktests 회귀 테스트에서 느린 완료나 존 장치 같은 동작을 흉내 내는 데 쓰인다는 것이다. 벤치마크 도구로만 소개하는 것은 정확하지 않다고 했다.
현재 커널의 Rust 드라이버는 두 부류로 나뉜다. 필요한 추상화를 직접 다 만들어가며 진행하는 대형 프로젝트(안드로이드 Rust binder, Nova, Tyr)와, 특정 장치를 위해 누군가 기여한 작은 드라이버다. 후자는 2026년 8월 기준 네트워크 장치 두 종류(AX88796B, QT2025), TH1520 PWM 컨트롤러, CPU 주파수 관리 정도로 많지 않다. 하지만 커널에는 방치된 틈새 장치 드라이버가 길게 늘어서 있고, 정확한 커널 C를 쓸 자신이 없는 사람에게는 이쪽이 오히려 Rust로 얻을 것이 많다. rnull은 블록 장치 쪽에서 그 청사진 역할을 한다.
스틸 타임으로 vCPU 수요를 스스로 줄이기
가상화는 적은 수의 물리 CPU를 많은 vCPU가 나눠 쓰게 해 사용률을 올린다. 하지만 실제로 쓸 수 있는 CPU 시간이 늘어나는 것은 아니어서, 너무 많은 vCPU가 바쁘게 돌면 경합과 성능 손실로 이어진다. 더 나쁜 경우는 락을 쥔 vCPU가 선점당하는 상황이다. 물리 CPU를 잡고 있는 다른 스레드들이 풀릴 수 없는 락을 붙들고 스핀하며 시간을 낭비하게 된다. Shrikanth Hegde의 steal governor 패치 시리즈는 게스트가 경합을 감지하면 스스로 요구를 줄이도록 하는 접근이다.
vCPU가 물리 CPU를 기다린 시간이 “스틸 타임(steal time)”이고, /proc/stat이나 top·vmstat으로 볼 수 있다. 이 값을 경합 정도의 지표로 삼아 “선호 CPU(preferred CPU)” 집합을 유지하는 것이 패치의 골자다. 선호 집합은 게스트가 가진 활성 vCPU의 부분집합이고, 커널은 가능한 한 이 집합 위에서만 태스크를 스케줄하고 나머지는 놀린다. 부팅 시에는 모든 CPU가 선호 집합에 들어가 있다가, 스틸 타임이 높아지면 CPU가 빠지고 낮아지면 다시 들어온다.
스케줄러가 선호 집합을 쓰는 방식은 세 군데다. 잠든 태스크를 깨울 때는 가능하면 선호 CPU에 올리고, 스케줄러 틱마다 현재 CPU가 선호 집합에 없으면 실행 중인 태스크를 선호 CPU로 밀어내며, 로드 밸런싱은 선호 집합 밖 CPU로 태스크를 옮기지 않는다. 예외는 태스크의 CPU 어피니티로, 선호 집합 밖에서만 실행 가능한 태스크는 그대로 그곳에 배치된다.
“결국 문제를 옮기기만 하는 것 아니냐”는 반론이 가능하다. 물리 CPU가 감당 못 할 부하는 게스트가 쓰는 vCPU 수를 줄인다고 사라지지 않는다. 달라지는 것은 선점 결정이 게스트 안으로 들어온다는 점이다. 워크로드와 태스크 우선순위를 아는 쪽에서 결정하므로, 우선순위가 높거나 경합 락을 쥔 태스크를 먼저 돌릴 수 있다.
정책은 steal_governor라는 “드라이버”에 담겨 있는데, 실제로는 드라이버가 아니라 자신을 계속 재등록하는 워크큐 아이템이다. 파라미터는 세 개다.
| 파라미터 | 기본값 | 역할 |
|---|---|---|
interval_ms | 1000ms | 스틸 타임을 확인하는 주기 |
low_threshold | 2% | 이 아래로 떨어지면 코어 하나 분량의 CPU를 선호 집합에 복귀 |
high_threshold | 5% | 이 위로 올라가면 하우스키핑 CPU가 없는 코어 하나를 선호 집합에서 제거 |
이 값들이 sysfs가 아니라 모듈 파라미터로 구현돼 있다는 점이 걸린다. 최근 몇 년간 권장되지 않는 방식이고, 값을 바꾸려면 steal_governor 모듈을 내렸다 다시 올려야 한다. sysfs나 sysctl 노브로 못 할 이유가 없어 보이고, 나아가 사용자 공간에서, 혹은 BPF 프로그램으로 선호 집합을 직접 제어하고 싶다는 요구가 나올 것이 거의 확실하다.
더 근본적인 한계는 이 메커니즘이 전적으로 자발적이라는 점이다. 전역 제어나 통신 채널 없이 게스트마다 독립적으로 반응할 수 있다는 게 장점이지만, 결과적으로 모두의 협조에 의존하는 구조가 된다. 일부 게스트만 선호 CPU 수를 줄이면 그쪽만 손해를 본다. 협조를 기대할 수 없는 멀티테넌트 환경에서 적용 범위가 제한될 수 있는 대목이다. 이에 대해 기사 댓글에서는 호스트 스케줄러가 공정하다면 협조하는 게스트도 같은 몫을 받아야 하고, 비협조 게스트는 타임 슬라이스를 소진하고 선점당할 테니 호스트 cgroup 설정으로 불이익이 없게 만들 수 있지 않느냐는 반론이 제기됐다.
협조가 가능한 환경에서의 결과는 좋아 보인다. 커버 레터의 벤치마크는 schbench에서 약 2%, 일부 hackbench 실행에서 44% 이상의 개선을 보여준다. 이 시리즈는 2025년 5월 첫 RFC 이후 11번의 리비전을 거쳤고, Hegde는 “이제 수렴했고 머지를 검토할 준비가 됐다”고 말했다. 다만 아직 Acked-by나 Reviewed-by 태그는 붙지 않았다.
GNOME 기술 거버넌스와 RFC 프로세스
Emmanuele Bassi가 GUADEC 2025에서 GNOME의 기술 거버넌스 개선을 제안한 지 1년이 지났다. 그의 진단은 “개인 프로젝트와 취향에 대한 과의존” 때문에 GNOME이 “‘비전’을 들고 나타난 누군가가 몰고 다니는 고양이 무리”가 됐다는 것이다. 소프트웨어 품질은 좋아졌지만, 그것은 소수가 다수의 컴포넌트를 떠맡은 결과라 일관성은 얻되 메인테이너는 번아웃 위험에 놓인다.
그가 제안한 것은 개인 메인테이너 모델을 없애고 공동 책임으로 가는 것, 영역별 팀(플랫폼·코어 앱·툴링 등)을 두는 것, 팀 대표로 구성된 운영위원회를 만드는 것, 그리고 변경 제안 프로세스를 도입하는 것이었다. 이 중 개인 메인테이너 폐지가 가장 큰 반발을 샀다. Adrian Vovk는 GNOME에 “이런 관료적 프로세스”를 굴릴 만큼 사람이 많지 않다고 했고, Michael Catanzaro는 “GNOME은 작은 프로젝트들의 큰 모음이고, 범위와 시야가 넓은 팀은 작은 프로젝트를 다루는 더 나은 방식이 아니다”라고 했다. 다만 팀이 개인 메인테이너를 오버룰할 권한을 갖는 것은 괜찮다고 했다. Allan Day는 팀·운영위·RFC를 한꺼번에 하는 것이 과하다며 가장 어려운 팀 구성을 분리해 시간을 더 주자고 제안했다.
GUADEC 2026에서 Bassi가 내놓은 후속 보고는 진도가 기대보다 느렸다는 것이다. “‘사기가 오를 때까지 거버넌스는 계속된다’로 제목을 달까 했는데 너무 노골적이라 관뒀다.” 제안이 논쟁적일 줄 알았는데 오히려 다들 개선이 필요하다는 데 동의했고, 문제는 정작 작업하는 사람이 없어 “서로가 서로를 쳐다보며 누가 와서 뭘 하라고 말해주기를 기다리는” 상황이 됐다는 것이다.
그래도 팀 구조는 진전이 있다. 팀의 정의와 활성/비활성 판정 규칙이 생겼고, GNOME Project Handbook에 팀 챕터가, GitLab에 팀별 공간이 마련됐다. 현재 바인딩 팀이 있고, 플랫폼 라이브러리 작업자들을 “포켓몬처럼 수집”해 플랫폼 팀을 만드는 중이다. 새 기능이든 새 설정이든 새 위젯이든 코어 라이브러리에 기여하려면 플랫폼 팀과 이야기하라는 것이 목표다. 반대로 문서화 팀처럼 활동이 없는 팀도 드러났다. 반면 운영위원회는 아직이다. 누가 얼마 동안 위원이 되는지, 의사결정 기구인지 중재 기구인지, “커뮤니티가 관심 없는 방향으로 소수가 프로젝트를 끌고 가는” 상황을 어떻게 막을지가 모두 미해결이다.
RFC 프로세스는 Bassi가 의도적으로 손을 뗀 영역이다. “괴짜 무리를 걸려 넘어지게 하는 건 규칙 따지기(rule lawyering)만 한 게 없다”며, 괴짜들이 관료제보다 더 싫어하는 건 자기들이 만든 관료제뿐이라고 했다. 대신 Sofie Herold가 7월 27일 RFC-0001 초안으로 논의를 시작했다. 흥미롭게도 이 RFC는 Bassi 제안의 대안 형태로, “한 묶음으로 논의하기에는 너무 많은 측면과 세부를 다루는 제안에 발이 묶이는” 것을 피하려고 범위를 줄였다.
초안에 따르면 RFC는 GitLab의 GNOME/rfcs 저장소에 MR로 올리고 포럼에 논의 스레드를 만든다. GNOME 재단 회원이면 누구나 만들 수 있고, MR 코멘트를 재단 회원으로 제한할 수 있다. “이해관계자(stakeholder)”는 “제안된 변경으로 GNOME에서의 작업이나 프로젝트가 유의미하게 영향받는 사람”으로 정의되고, 어떤 팀의 구성원 두 명이 자기 팀이 이해관계자라고 판단하면 반드시 추가해야 한다. 반대 의견은 “concern”으로 제기하고 제기자 본인을 제외한 이해관계자가 수용할 수 있다. 최종 의견 수렴 기간은 14일이며, 그 뒤 이해관계자 누구든 MR을 머지(수락)하거나 닫을(거부) 수 있다.
절차가 얼마나 촘촘해야 하느냐는 질문에 Matthias Clasen은 RFC가 가볍고 인지 확산에 집중해야 한다는 쪽에 섰다. Bassi가 RFC 대상 예시로 든 변경들(문서 포맷 전환, 권장 이미지 로더 라이브러리 교체)조차 “코드를 쓰기 전에 모든 가능성과 희박한 실패를 놓고 우려 가득한 논의를 길게 했다면 완료되지 못했을 것”이라는 것이다. 8월 31일 Sam Thursfield는 “일단 프로세스를 채택하고 쓰기 시작하는 게 최선”이라고 했고, Herold도 9월 4일까지 새 우려가 없으면 최종 의견 수렴 기간을 공지하겠다고 했다. “그냥 RFC 프로세스를 쓰기 시작하고 배운 것을 나중에 반영하는 게 나을 것 같다.”
커널 7.3 머지 윈도우 후반부
7.3-rc1이 나오면서 머지 윈도우가 닫혔고, 병합 커밋을 뺀 15,267개의 체인지셋이 메인라인에 들어갔다. 커널 역사상 rc1 기준 두 번째로 큰 수치이고, 이보다 많았던 것은 bcachefs 히스토리 3천 커밋가량이 포함된 6.7-rc1뿐이다. 이 중 약 1만 3천 개가 머지 윈도우 전반부 요약 이후에 들어왔다.
스케줄러·트레이싱·메모리
- sched_ext의 서브 스케줄러 기능이 남은 조각까지 머지되어 완성·동작 상태로 선언됐다. 머지 메시지의 표현으로는 “루트 BPF 스케줄러가 cgroup 서브트리를 회수 가능한 CPU 할당과 함께 중첩 서브 스케줄러에 넘길 수 있고, 서브 스케줄러는 그 CPU들에서 자기 태스크의 모든 스케줄링 결정을 소유한다”.
- 동적 프로브(
kprobes,uprobes,fprobes)가 BTF 데이터를 이용한 간단한 타입 캐스팅을 할 수 있었는데, 7.3에서 그 범위가 크게 확장됐다. 부팅 시점 프로브 지원도 개선됐다. - 가상 머신의 워킹셋 추적이 개선됐다. LWN이 별도로 다룬 이 작업은 “지금까지 머지된 LLM 보조 코어 코드 중 가장 큰 덩어리”라고 할 만하다.
- DAMON이 데이터 속성만 모니터링하는 모드를 지원한다. 어떤 메모리가 접근되는지보다 접근되는 메모리의 종류에 관심 있는 사용자를 위한 것이다.
- kexec 핸드오버(KHO)가 부팅 시점에 할당된 huge page를 다루는 방식이 개선됐다.
- 확장(expedited) RCU 유예 기간이 이제 일반 콜백까지 함께 호출한다. 메모리 할당 프로파일링에는 새
ioctl()명령이 생겨, 데이터를 사용자 공간에 넘기기 전에 커널이 불필요한 정보를 걸러낼 수 있게 됐다(성능이 크게 개선된다). - 스왑 서브시스템의 저수준 내부가 새
swap_ops구조체를 중심으로 재작업됐다.
KHO 항목은 기사 댓글에서 곧바로 정정됐다. KHO는 아직 HugeTLB 페이지 보존을 지원하지 않는다(THP는 동작할 수 있다). 1G huge page는 KHO 초기화보다 먼저 할당되는데, 커널은 이른 부팅 단계에서 어느 페이지가 보존 대상인지 모르기 때문에 “스크래치 버퍼”라는 사전 할당 영역에서 초기 할당을 처리한다. 이 버퍼는 다음 커널을 위해 비어 있어야 하므로 여기서 나온 1G 페이지는 보존될 수 없었다. 이번 변경은 1G huge page를 스크래치 밖에서 할당할 수 있게 한 것으로, 보존 자체를 해결한 게 아니라 그 전제 조건을 갖춘 것이다. Corbet은 “huge page로서 보존될 수 있게 한다는 뜻으로 썼는데 표현이 더 나을 수 있었다”고 답했다.
파일시스템과 블록 I/O
ntfs3가 대체 데이터 스트림(alternative data stream)을 기본 지원한다. 파일 이름에 콜론을 붙여 접근하며, 예를 들어cat file:query_streams로 파일에 딸린 스트림 목록을 볼 수 있다. 경쟁 관계인ntfs파일시스템은 Windows overlay filter(WOF) 압축을 읽기 전용으로 지원하게 됐다.- NFS 서버가 디렉터리 위임에
CB_NOTIFY를 지원한다. 디렉터리 안의 구체적 변경을 상대에게 알릴 수 있어 캐시를 유지할 수 있는 경우가 많아진다. - Btrfs 프리스페이스 캐시 v1 지원이 6.11부터 deprecated였는데 7.3에서 완전히 제거된다. 기존 파일시스템도 동작은 하지만 느려질 수 있고,
btrfstune으로 v2로 전환할 수 있다. 5.9부터 deprecated였던usebackuproot마운트 옵션도 제거됐다(rescue=usebackuproot를 쓸 것). - 블록 장치에 대한 버퍼 I/O에
RWF_DONTCACHE플래그를 쓸 수 있게 됐다. 데이터를 페이지 캐시에 남기지 않는 용도다. ksmbd가 Apple Time Machine 지원, 공유별 SMB3 암호화, SMB Direct RDMA 암호화 등 여러 기능을 추가했다. FUSE는 io_uring과 함께 쓸 때의 버퍼 풀과 제로카피 I/O 지원이 개선됐다.- F2FS가 파일시스템 풀에서 파티션을 동적으로 제거했다가 나중에 되돌리는 기능을 얻었다.
보안·BPF·그 밖의 변경
- 새 sysctl 노브
crypto/af_alg_restrict가 사용자 공간의AF_ALG암호화 API 접근을 규제한다. 기본값은 부분 제한이고, 이 기능 자체가 앞으로 완전히 제거될 수도 있다. - 서명된 BPF 프로그램 검증이 강화됐다. 로드 전에 커널이 프로그램 메타데이터의 무결성을 검증한다.
landlock_restrict_self()에LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS플래그가 추가됐다. 새 룰셋 설정이 성공한 뒤에만 “no new privileges” 플래그를 설정한다. AppArmor는 압축된 정책 로딩을 지원한다.- BPF kfunc에
KF_SPINLOCK_SAFE플래그를 달아 스핀락을 쥔 채 호출해도 안전함을 표시할 수 있다. 아레나 포인터 전달도 쉬워져서, 파라미터 이름에__arena접미사를 붙이면 자동으로 아레나 공간 기준으로 오프셋되고 적절한 타입으로 캐스팅된다(NULL이 올 수 있는__arena__nullable변형도 있다). BPF 프로그램이 전역 per-CPU 데이터에 접근할 수 있게 됐고, 검증기(verifier)는 검증 실패 시 더 많은 정보를 준다. - Rust 지원으로 I/O 타입과 프로젝션, fwctl API, sleepable RCU(SRCU)가 추가됐다. 새
rvwakeup 모니터는 저우선순위 태스크가 실시간 태스크를 깨우는 상황(우선순위 역전의 징후)을 보고한다. - VXLAN·GENEVE로 관리되는 UDP 터널에서 big TCP 패킷을 쓸 수 있게 됐다. s390은 제네릭 cpuidle 기반 서브시스템과 Clang 소프트웨어 기반 제어 흐름 무결성 지원을 얻었다.
- 익스포트 심볼은 153개가 제거되고 523개가 추가됐다. kfunc은 3개 제거, 32개 추가다.
7.3-rc1은 2,450명이 기여했고 그중 520명이 첫 기여자다. 커밋 1,264개(전체의 8% 남짓)에 Assisted-by 태그가 붙었는데, Corbet은 이것이 커널의 실제 LLM 보조 커밋 수를 크게 과소평가한 수치일 것이라고 봤다. 7.3 릴리스는 10월 18일이 유력하다. 7.2에서 rc1 이후 3천 개 넘는 커밋이 들어간 패턴이 반복된다면 7.3은 역대 최다 커밋 릴리스가 된다.
LUKS 디스크의 암호화 키가 절전 시 남아있던 버그
노트북이 잠들어 있어도 메모리를 읽을 수 없는 것은 아니다. 적절한 장비로 메모리 버스에 붙으면 내용을 읽을 수 있고, 콜드 부트 공격은 전원이 끊긴 뒤 짧은 시간 동안 메모리 값을 읽어낼 수 있다. 그래서 일부 사용자는 절전에 들어갈 때 전체 디스크 암호화 키만이라도 지워지기를 원한다. 그런데 2026년 6월 Ingo Blechschmidt가 6.9(2024년 5월) 이후 커널이 그렇게 설정해도 키를 지우지 않고 있었다는 사실을 발견했다.
이 기능이 기본값이 아닌 이유부터 보면 상황이 이해된다. 키를 지우면 디스크 읽기가 모두 블록되므로, 루트 디스크의 키를 지우고 잠들면 깨어날 때 스크린 락커 실행 파일을 읽으려다 시스템 전체가 데드락에 빠지기 십상이다. Debian은 이 문제를 램디스크로 푼다. 절전 준비 단계에서 암호 입력에 필요한 프로그램과 설정 파일을 램디스크에 올려두고 키를 지운 뒤 잠들고, 깨어나면 램디스크의 프롬프트 프로그램이 먼저 돌아 디스크를 풀고 키를 커널 키링에 넣는다. 이후의 디스크 접근이 성공하므로 나머지 사용자 공간이 정상적으로 깨어난다. Debian은 이를 cryptsetup-suspend로 패키징했고 여러 배포판으로 포팅됐다.
Blechschmidt는 이것을 NixOS로 포팅하다가 테스트용 가상 머신 메모리에 암호화 키가 그대로 남아있는 것을 발견했다. 추가 테스트로 원인이 커널에 있음을 확인했다. “몇 년 동안 신뢰해온 보안 메커니즘이 실은 그 일을 한 번도 하지 않았다는 걸 알게 되는 건 유독 불편한 데가 있다.”
원인은 2024년 Christian Brauner가 device-mapper 코드를 핸들 기반 인터페이스에서 블록 장치 파일 디스크립터 기반 인터페이스로 정리하면서 바꾼 한 줄이었다.
/* 변경 전 */
bdev_handle = bdev_open_by_dev(dev, mode, _dm_claim_ptr, NULL);
/* 변경 후 */
bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);왜 이것이 문제가 되는지는 바로 보이지 않는다. 실제 버그는 블록 장치 연산을 요청한 프로세스의 스레드 키링이 어떻게 다뤄지는가에 있다. 사용자 공간 프로세스가 암호화 디스크의 device-mapper 장치에 대한 참조를 얻으면(예를 들어 cryptsetup이 키를 지워 디스크를 다시 잠그라고 요청할 때) 생성된 bdev_file이 스레드 키링에 대한 참조를 붙든다. 예전 핸들 기반 인터페이스는 그러지 않았다. 커널의 struct file이 관련 자격증명을 캐시하는 것 자체는 대체로 합리적이지만, 이 경우 커널은 해당 사용자 공간 프로세스가 종료된 뒤에도 파일 참조를 유지한다. 그러면 디스크 암호화 키 사본이 든 스레드 키링이 계속 살아 있어, 커널이 요청대로 자기 사본을 지워도 키링 안의 사본은 남는다.
7.2에 머지된 수정은 파일 생성 시 스레드 키링 대신 커널 자신의 자격증명을 쓰게 하는 것이다.
scoped_with_kernel_creds()
bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);이렇게 하면 cryptsetup이 종료되는 즉시 스레드 키링이 해제되고, 요청대로 커널의 키 사본도 지워진다. 하지만 7.2 이전 커널을 써야 하는 사람에게는 도움이 되지 않는다. cryptsetup 메인테이너 Ondrej Kozina는 명시적으로 폐기(revoke)할 수 있는 중간 키링을 하나 더 만드는 우회책을 도구 쪽에 추가했다. 버그 있는 커널이 스레드 키링의 키를 붙들고 있더라도 그 키로는 디스크의 주 암호화 키에 접근할 수 없게 되는 방식이며, 7월 말 2.8.7 릴리스에 포함됐다. Kozina는 키링을 명시적으로 해제하는 것이 어느 쪽이든 중요한 예방 조치라고 했다. 키링을 붙들 수 있는 커널 서브시스템이 여럿이라, 그중 무엇도 잘못 호출되지 않았음을 보장하는 것보다 cryptsetup 쪽에서 막는 편이 견고하다는 것이다. 실제로 이번 커널 수정은 물리 장치를 백엔드로 하는 암호화 블록 장치에만 적용되고, 루프백 인터페이스 등으로 뒷받침되는 구성은 여전히 버그를 만날 수 있다.
NixOS 포팅은 결국 성공했고, Blechschmidt는 절전 시 키가 제대로 지워지는지 검증하는 통합 테스트까지 NixOS에 추가해 같은 버그가 다시 들어오지 못하게 했다. 그의 구현은 Debian 방식의 사소한 경합도 없앴다. cryptsetup-suspend는 키를 먼저 지우고 그다음에 커널에 절전을 요청하기 때문에, 그 사이에 디스크에 접근하려는 커널 태스크가 키를 기다리며 멈추는 짧은 창이 있다. 이렇게 되면 컴퓨터가 잠들지 못하는데, 잘해야 성가시고 나쁘면 과열로 이어진다. NixOS 버전은 커널 패치로 키 삭제와 절전 진입을 동시에 처리해 이 경합을 없앤다. 다만 깨어난 뒤 암호를 입력받기 위한 램디스크는 여전히 필요하다.
LWN 구독료 인상
LWN이 9월 15일부터 구독료를 올린다. 2002년 말 구독 모델을 도입한 이후 24년간 인상은 두 번뿐이었고, 마지막이 2022년 초다. 그 사이 미국 소비자물가 상승은 약 20%였고 건강보험 같은 일부 비용은 그보다 더 올랐다. 인상폭은 물가 상승률에 맞춘 약 20%다.
| 등급 | 새 월 구독료 |
|---|---|
| Starving hacker | $6.00 |
| Professional hacker | $11.00 |
| Project leader | $19.00 |
| Maniacal supporter | $55.00 |
그룹 구독도 같은 비율로 오른다. 변경 전에 구매한 구독은 원래 만료일까지 유효하고, 이번에는 월간 구독 정책이 조금 다르다. 공지 발송 이전에 활성 상태였던 월간 구독은 이후 6개월간 기존 요금으로 청구된다. 2022년 인상으로 Daroc Alden과 Joe Brockmeier를 채용해 커버리지를 넓혔고 EPUB 기사, 커널 소스 데이터베이스, 전문 이메일·RSS 피드, 다크 모드, 공개 토픽 목록 같은 기능을 추가했다는 설명도 덧붙었다. 구독자 증가가 최근 몇 년 정체된 것이 이번 인상의 배경이다. LWN은 내년 1월 발행 30년차에 들어간다.
짧은 소식
- git.kernel.org 트래픽의 대부분이 스크레이퍼: Konstantin Ryabitsev가 AI 크롤러의 영향을 수치로 공개했다. git.kernel.org는 무작위 커밋을 요구하는 요청을 하루 약 600만 건 받는다. 이 중 66%는 Anubis 챌린지로 즉시 걸러지지만, 나머지 33%는 실제로 연산을 풀고 사이트에 들어온다. “우리가 제공하는 것이 Anubis 챌린지 계산에 엄청난 사이클을 쓸 만한 가치가 있다는 뜻이다.” 봇과 사람을 확실히 구분할 수는 없지만 오래된 포크의 오래된 커밋을 요구한다면 실제 개발자일 가능성은 낮고, 후하게 잡아도 정상 요청은 전체의 2% 정도라는 것이 그의 추정이다.
- Debian, “생성형 AI의 책임 있는 사용” 가결: LLM 사용에 관한 Debian 일반결의 투표에서 5번 선택지 “Responsible Use of Generative AI”가 채택됐다. Debian은 개발·유지보수·문서화에서 생성형 AI 도구 사용을 지지하지도 금지하지도 않되, 도구와 무관하게 모든 기여가 동일한 품질·정확성·유지보수성·법적 준수 기준을 만족해야 한다고 명시했다. “생성형 AI 도구를 썼다고 해서 기여자가 제출물에 대해 지는 책임이 줄어들지 않는다.”
- sparse 메인테이너 구함: 토발즈가 sparse 유지보수가 또 끊긴 것 같다며 아무도 나서지 않으면 자기가 최소한으로 맡아볼 수 있다고 했다. 다만 자신이 sparse를 실제로 작업한 것은 2006년 9월이 마지막이라며 “내 microemacs ‘유지보수’처럼 산발적으로, 아마 LLM을 써서 할 것”이라고 덧붙였다. “이건 이걸 정말로 맡고 싶은 불쌍한 영혼을 낚는 낚시이기도 하다. 누군가 ‘나는 LLM을 쓰겠다’를 협박으로 받아들인다면, 정확히 그런 의도로 한 말이니까.”
- 보안 이슈 비공개 관행에 대한 지적: Michael Catanzaro는 보안 버그 리포트가 영원히 비공개로 남으면 오픈소스 프로젝트의 보안을 평가할 방법이 없다고 지적했다. GNOME에서는 MR이 생성되거나 수정이 git에 들어갔을 때, 또는 리포트 후 30일 중 먼저 오는 시점에 공개한다. 프로젝트마다 기준은 다를 수 있지만 “잊어버리고 영원히 비공개로 두지는 말라”는 것이다.
- Dolphin 26.08과 KIO 성능: Méven Car가 Dolphin 파일 관리자와 KIO 프레임워크의 성능 작업을 정리했다. 작은 파일을 많이 복사하는 경우가 4월 대비 두 배 이상 빨라졌다. 파일이 커질수록 이득이 줄어드는데, 수정한 것이 파일당 오버헤드라 파일 하나가 1MB씩 실제 I/O를 지고 나면 그 오버헤드는 더 이상 병목이 아니기 때문이다.
cp와의 격차는 아직 남아있고, 그 차이를 대부분 좁힐 배치 처리 작업이 진행 중이다. - 릴리스 소식: Firefox 155(주소창에 차단한 광고 트래커 수 표시, 컨테이너 순서 변경,
mailto:링크를 명시적 사용자 동작으로만 열기, 캡티브 포털 감지 도메인을 detectportal.firefox.com에서 firefox-portal-detection.com으로 변경 — 네트워크 허용 목록 수정이 필요할 수 있다), Incus 7.4(UEFI 시큐어 부트 키 관리, 인스턴스 간 컨테이너 “준 라이브” 마이그레이션, 디스크·네트워크 장치의 버스트 I/O 제한), OpenShot 4.0(화면·웹캠·마이크·시스템 오디오 녹화, 컬러 휠·커브·LUT·비디오 스코프, 로컬 실행 머신러닝 모델을 이용한 피사체 분리). - 스테이블 업데이트: 8월 27일 7.2.1, 7.1.11, 6.18.47, 6.12.106, 6.6.154, 6.1.185, 5.15.218, 5.10.267이, 28일 단일 수정 업데이트가, 9월 2일 7.2.3, 7.1.13, 6.18.49, 6.12.108, 6.6.156, 6.1.187, 5.15.220, 5.10.269가 릴리스됐다. 7.1.13이 7.1 계열의 마지막 업데이트다.
- Netdev 0x1A 자료 공개: 7월 13~16일 로마에서 열린 Netdev 0x1A의 전 세션 영상과 슬라이드가 공개됐다. Linux QUIC, 공유 메모리 소켓 전송, eBPF 기반 DDoS 방어 등을 다룬다.
이번 주 핵심 요약
- Python JIT 사안의 본질은 기술 논쟁이 아니라 절차 논쟁이다. 정보성 PEP 하나에 기대 2년 넘게 진행된 기능을 정식화하려니, 지금 와서 쓰는 PEP가 “이미 있는 코드를 문서화하는 것”인지 “앞으로 만들 JIT를 제안하는 것”인지가 흐려졌다. Wouters가 요구한 시작 시간·워밍업·메모리 오버헤드 추적은 JIT를 켤지 말지 판단하는 실무자 입장에서도 가장 필요한 숫자다. LLVM 버전 고정 문제(3.14는 LLVM 19, 3.15는 LLVM 21, 둘 다 EOL)는 배포판 패키징에 당장 걸리는 제약이니 PEP 774의 진행도 함께 볼 것.
- rnull에서 눈여겨볼 것은 요청 처리 로직이 아니라 그 주변 뼈대다.
pin_init_scope()로 모듈 데이터를 핀 고정하고,#[vtable]로 C 쪽이 기대하는 함수 포인터 구조체를 만들고, const 제네릭으로 configfs 속성마다 vtable을 생성하는 패턴은 다른 블록 드라이버에도 거의 그대로 재사용된다. 성능은 “대부분 구분되지 않는다” 수준이니, 이제 Rust 블록 드라이버의 걸림돌은 오버헤드가 아니라 추상화의 성숙도다. - steal governor는 공용 클라우드보다 자기 하이퍼바이저를 직접 운영하는 환경에서 먼저 쓸모가 있다. 전적으로 자발적인 메커니즘이라 협조하지 않는 게스트가 섞이면 협조하는 쪽만 손해를 보기 때문이다. 파라미터가 sysfs가 아니라 모듈 파라미터라 튜닝하려면 모듈을 내렸다 올려야 한다는 점은 자동화를 짤 때 감안해야 한다.
- LUKS 키 잔존 버그는 리팩터링이 어떻게 조용히 보안 속성을 깨뜨리는지 보여주는 사례다.
bdev_open_by_dev()를bdev_file_open_by_dev()로 바꾼 것뿐인데, 새 인터페이스가 만드는struct file이 호출 스레드의 키링을 붙들면서 키가 살아남았다. 수정은 7.2에 들어갔지만 그 이전 커널을 쓴다면 cryptsetup 2.8.7 이상으로 올리는 것이 현실적인 대응이고, 루프백 백엔드 구성은 커널 수정 이후에도 여전히 영향을 받는다. - 7.3에서 운영에 바로 영향을 주는 항목은 Btrfs 프리스페이스 캐시 v1 완전 제거와
usebackuproot옵션 제거다. 오래된 파일시스템을 그대로 쓰고 있다면 업그레이드 전에btrfstune으로 v2 전환을 마쳐두는 편이 낫다. KHO의 huge page 항목은 “1G huge page를 보존할 수 있게 됐다”가 아니라 “스크래치 버퍼 밖에서 할당할 수 있게 됐다”는 전제 조건 단계이니 기대치를 조정할 것. - 커널 커뮤니티의 LLM 관련 신호가 이번 주에 세 갈래로 겹쳤다. 7.3-rc1 커밋의 8%에 Assisted-by 태그가 붙었고(실제로는 더 많을 것이라는 게 Corbet의 판단), Debian은 총회로 “책임 있는 사용”을 공식 입장으로 정했고, 토발즈는 sparse를 LLM으로 최소 유지보수하겠다는 말로 메인테이너를 구하고 있다. 한편 git.kernel.org 트래픽의 98%가 스크레이퍼라는 수치는 그 반대편 비용을 보여준다.