pile·
인프라 / DevOps·글루시스글루시스·

zfs userspace와 zfs create 사이의 EBUSY 레이스 수정

글루시스 이헌제가 OpenZFS 운영 중 겪은 `zfs create` 자동 마운트 실패 버그를 분석하고 upstream PR #18611로 병합된 수정 과정을 정리한다. 원인은 조회 성격의 `zfs userspace`가 마운트 경로와 동일하게 dataset의 배타적 소유(`ds_owner`)를 요구하도록 잘못 구현돼 있어, 10초 주기 모니터링 데몬과 `zfs create`가 겹치면 `EBUSY`가 튀는 레이스였다. 해결은 조회 경로를 소유(`own`) 대신 참조(`hold`)로 바꾸는 한 줄이었지만, 그 과정에서 config lock 생명주기와 ABBA 교착까지 함께 손봐야 했다.

핵심 포인트
  • `zfs create` 자동 마운트가 `mountpoint or dataset is busy` (EBUSY)로 간헐 실패, 재현 조건은 모니터링 데몬의 주기적 `zfs userspace/groupspace/projectspace` 호출과 동시성.
  • 원인은 세 잠금 중 `ds_owner`(mutex 보호, 배타적) 층에서의 선점 경쟁. 먼저 도착한 쪽이 owner를 잡으면 나머지는 EBUSY.
  • 진짜 문제는 잠금 자체가 아니라 설계 불일치. 쿼터 숫자를 읽기만 하는 조회 연산에 배타적 소유가 필요 없었다.
  • 수정은 `zfs userspace` 경로에서 `dmu_objset_own()`을 `dmu_objset_hold()`로 교체. config lock 순서 역전과 경로 분기 관리가 부수적으로 필요.
상세 정리
  • 문제 재현: `zfs create ci_zfsPool_1B/ci_zfsVol_beta` 후 자동 마운트가 실패하며 `filesystem successfully created, but not mounted` 로그. 스토리지 모니터링 데몬이 10초 주기로 쿼터 조회를 돌리는 환경에서만 재현.
  • 관여 잠금 세 개를 분리 분석: `z_teardown_lock`(zfsvfs 생명주기·inode 캐시 보호, R/W), `dp_config_rwlock`(풀의 dataset 트리·속성 보호, R/W), `ds_owner`(dataset 배타 소유 표시, mutex).
  • EBUSY 트리거 시퀀스: 조회 쪽이 임시 인스턴스를 만들려고 `dmu_objset_own(FTAG)` 호출 → `ds_owner=FTAG` 세팅 → 뒤이어 `zfs create`가 같은 dataset을 `own()` 시도하다 이미 소유자가 있어 EBUSY.
  • 근본 판단: `zfs userspace`는 값만 읽는 관측 연산이라 배타적 owner가 될 필요가 없다. `zfs create` 쪽만 `z_os` objset 연결 등 구조 변경이 있어 owner가 필수.
  • 해결책 함수 `zfsvfs_create_hold()` 신설. 마운트되지 않은 dataset을 대상으로 `dmu_objset_hold()`로 참조만 잡고, `dmu_objset_type()` 체크가 없는 hold의 특성상 `DMU_OST_ZFS`인지 명시적으로 확인한 뒤 `zfsvfs_create_impl()`로 임시 인스턴스 구성.
  • `zfsvfs_hold()`도 갈래를 분기. `getzfsvfs()`로 이미 마운트된 인스턴스가 없으면 신설 함수로 진입하고, teardown lock 진입 전에 config lock을 먼저 해제해 ABBA 교착을 예방.
  • ABBA 원인: `own()`은 config lock을 획득했다 반환 전에 놓지만 `hold()`는 유지한 채 반환한다. 그대로 두면 hold 경로가 `config(R) → teardown` 순서로 잠가 `zfs_resume_fs()`의 `teardown(W) → config` 순서와 교차한다.
  • 경로 구분 실패 사례: 처음엔 `ds_owner != NULL`로 hold/own을 구분하려 했으나 이 필드가 mutex 보호라 검사 자체가 새 레이스가 됨. 대신 `zfsvfs_t`에 `z_use_hold` boolean을 두고 `zfsvfs_create_hold()`가 딱 한 번 세팅.
  • `zfsvfs_rele()`도 대칭 처리. `z_use_hold`면 config lock을 재획득 후 `dmu_objset_rele()`, 아니면 기존대로 `dmu_objset_disown(..., B_TRUE, ...)`.
  • 검증은 userspace/groupspace/projectspace 각각에 대해 `zfs mount &` 백그라운드와 조회를 50회 부딪히는 스트레스 케이스를 회귀 테스트로 추가. 수정 후 EBUSY 재현이 사라짐을 확인.
  • 결과 PR은 OpenZFS upstream #18611로 병합. 코드 변경 자체는 조회 경로 하나지만, 잠금 순서와 경로 플래그 관리까지 파생돼 최종 diff가 커진 사례.
왜 읽나파일시스템/스토리지 저수준을 만지는 커널·시스템 엔지니어에게 "원인은 rwlock이 아니라 API 선택"이라는 진단 관점과, hold/own·config lock·teardown lock의 ABBA를 실제 코드로 해결한 참조 자료.
글루시스
글루시스 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 인프라 / DevOps·KT 클라우드KT 클라우드·

    [구축사례] kt cloud PLATFORM Observability Alert 플랫폼 구축하기

    KT Cloud Data Platform 팀이 KCP 클라우드 환경에서 LGTM 스택(Grafana, Loki, Tempo, Mimir)을 기반으로 자체 Alert 관리 서비스를 구축한 사례를 다룬다. 조직별 격리·통합관제 연동·이력 관리를 목표로 외부 SaaS 없이 오픈소스만으로 엔터프라이즈급 Alert 체계를 완성했다.

    요약 이어보기
    #observability#multi-tenancy#grafana+2
  2. 인프라 / DevOps·KT 클라우드KT 클라우드·

    [AI활용] Claude 실무편 - kt cloud VM에서 PR 리뷰 자동화하기

    KT Cloud FE개발팀이 PR 리뷰 병목 문제를 해결하기 위해 Claude 기반 자동화 시스템을 구축한 사례를 다룬다. "판단 기준은 사람이 정의하고, 검증 로직은 규칙으로 명시하며, 결과 설명은 AI가 수행한다"는 역할 분리 원칙 하에, kt cloud VM에서 poller 스크립트로 지속 실행하는 구조를 완성했다.

    요약 이어보기
    #llm-app#ci-cd#claude-api+2
  3. 인프라 / DevOps·AWS KoreaAWS Korea Tech·

    AI 기반 SCTE-35 자동 삽입으로 라이브 스트리밍 광고 운영 자동화하기

    AWS 기술 블로그가 라이브 스트리밍 광고 삽입을 자동화하는 서버리스 아키텍처를 소개한다. MediaLive 썸네일 API, Rekognition Custom Labels, Step Functions을 조합해 광고 대기 화면(필러)을 자동 감지하고 SCTE-35 신호를 즉시 삽입한다. 수동 조작이나 사전 스케줄 없이 실시간 이벤트 타이밍에 맞춘 광고 운영이 가능해진다.

    요약 이어보기
    #aws#live-streaming#step-functions+2