
백엔드
zfs userspace와 zfs create 사이의 EBUSY 레이스 수정
두줄요약
OpenZFS의 `zfs userspace`와 `zfs create`가 `ds_owner`에서 충돌해 `EBUSY`가 발생하는 레이스를 분석했습니다. 조회 경로를 `hold()` 기반으로 분리하고 잠금 순서를 조정해 업스트림 패치까지 반영했습니다.
문제 상황
- OpenZFS 기반 스토리지에서
zfs create직후 자동 마운트가 간헐적으로mountpoint or dataset is busy로 실패하는 레이스 - 모니터링 데몬의
zfs userspace조회가 같은 dataset을 먼저 잡아EBUSY를 유발하는 충돌 - 실패 시 dataset은 생성만 되고 마운트되지 않은 orphan 상태로 남는 문제
원인 분석
zfs userspace와zfs create가 모두dmu_objset_own()으로ds_owner를 선점하는 구조- 조회 연산임에도 마운트 경로와 같은 배타적 소유권을 요구해 충돌 발생
z_teardown_lock,dp_config_rwlock,ds_owner중 실제 레이스는ds_owner에서 발생
해결 방법
- 조회 경로를
dmu_objset_own()대신dmu_objset_hold()기반의zfsvfs_create_hold()로 분리 zfsvfs_hold()와zfsvfs_rele()에z_use_hold분기를 넣어 hold/own 경로를 구분dmu_objset_hold()의 config lock 유지로 생긴 ABBA 교착을 피하기 위해 teardown 전에 config lock 해제
주의할 점
dmu_objset_hold()는 객체셋 타입을 자동 확인하지 않아DMU_OST_ZFS가드가 필요ds_owner를 release 경로 분기 조건으로 직접 읽으면 레이스가 생길 수 있음- hold 전환은 단순 대체가 아니라 잠금 순서까지 함께 점검해야 함
적용해볼 점
- 조회 전용 경로와 배타적 변경 경로를 분리해 락 요구사항을 최소화
- 새로운 hold/rele 경로 도입 시 기존 잠금 순서와 교착 가능성 검증
- 레이스 재현용 테스트를 반복 실행 형태로 추가해 회귀 방지
