Watch at Ease세상을 읽고, 일상의 답을 찾다.

컴퓨팅 · 실용 가이드

Linux의 “Invalid cross-device link”: rename·복사·게시를 고르기 전에 마운트 경계를 입증하세요

EXDEV는 경로 문자열 문제가 아니라 계약 경고입니다. 호출자의 마운트 네임스페이스에서 두 경로를 매핑하고 원자적 rename이 필요한지 결정한 뒤, 파일시스템 간 복사는 원본을 지우기 전에 대상에서 스테이징하고 검증해야 합니다.

원본 마운트 ID 42와 대상 ID 77 사이에 EXDEV가 표시된 비교 도표
개념 일러스트: 경로 이동을 rename으로 보기 전에 호출자 네임스페이스에서 마운트 ID를 비교합니다. Watch at Ease

Linux는 rename이 하나의 마운트된 파일시스템 안에서 이동을 수행할 수 없을 때 EXDEV를 반환하며, 보통 “Invalid cross-device link”로 표시됩니다. 디렉터리 이름이 비슷해도 bind mount, 컨테이너 볼륨, tmpfs, overlay 레이어, 별도 파일시스템 때문에 서로 다른 마운트 ID가 될 수 있습니다. 코드나 권한을 바꾸기 전에 실패한 프로세스와 같은 마운트 네임스페이스에서 두 경로를 조사하세요.

파일시스템 간 대체 동작은 rename을 흉내 낸 것이 아닙니다. 복사, 검증, 성공 후 원본 삭제로 이루어진 별도의 작업입니다. 독자에게 불완전한 대상을 보여서는 안 된다면 대상 파일시스템의 임시 객체에 쓰고, 플러시와 검증을 마친 다음 같은 대상 마운트에서 최종 이름으로 rename하세요. 도구와 대상이 실제로 보존하는 메타데이터만 약속하고, 마운트 간 이동 전체는 원자적이지 않다고 명시해야 합니다.

1. 실패한 작업과 네임스페이스를 기록하세요

실제 호출자가 사용한 원본, 대상, 프로세스 ID, 컨테이너 또는 서비스 문맥, 반환된 오류를 기록하세요. 컨테이너나 private 마운트 네임스페이스에서 실패했다면 호스트 셸에서만 재현하지 마세요. 같은 문자열도 다른 마운트 테이블로 해석될 수 있습니다.

단순 이동인지, 기존 이름 교체인지, 독자에게 all-or-nothing 결과를 약속하는 게시 단계인지도 기록하세요. 이 요구가 copy-and-delete 허용 여부를 결정합니다.

2. 두 경로를 마운트 ID에 매핑하세요

호출자의 네임스페이스에서 원본과 대상 디렉터리에 findmnt --target을 실행하세요. 다른 프로세스를 조사할 때는 권한 범위에서 findmnt --task PID 또는 /proc/PID/mountinfo를 사용하세요. 디렉터리 접두사 대신 마운트 ID, root, mount point, 파일시스템 유형, source를 비교합니다.

최종 파일이 아직 없다면 대상 부모 디렉터리를 확인하세요. bind mount는 같은 하위 장치라도 다른 마운트 ID를 가질 수 있고, rename(2)은 같은 파일시스템이 두 곳에 마운트됐더라도 마운트 사이 rename이 거부될 수 있다고 설명합니다.

3. 작업에 필요한 보장을 결정하세요

하나의 원자적 네임스페이스 변경이 필요하면 임시 이름과 최종 이름을 같은 마운트에 두고 그곳에서 rename하세요. 무조건 파일시스템 간 복사를 추가하지 말고 임시 디렉터리, 작업공간, 볼륨, 게시 스테이징 경로를 재구성합니다.

일시적 중복과 전체 이동의 비원자성을 허용할 수 있다면 복사 워크플로도 맞을 수 있지만 보장을 명시해야 합니다. 대상 검증이 끝날 때까지 원본을 권위 있는 사본으로 취급하세요.

4. 대상 파일시스템에서 스테이징하고 검증하세요

대상 디렉터리에 고유한 임시 이름을 만들고 데이터를 복사한 뒤, 내구성 정책에 맞게 닫고 플러시하고 크기 또는 암호학적 다이제스트를 검증하세요. mode, owner, timestamp, ACL, 확장 속성, symlink 정체성, sparse 할당은 복사 방식마다 보존되지 않을 수 있습니다.

검증 후 대상 측 임시 객체를 최종 이름으로 rename하세요. 두 이름이 같은 마운트에 있으므로 마지막 rename은 원자적으로 수행될 수 있습니다. 원본을 삭제하기 전에 최종 객체와 접근 정책을 확인합니다.

5. EXDEV를 숨기지 말고 실패 경계를 시험하세요

복사 완료 전, 검증 후, 대상의 로컬 rename 후, 원본 삭제 전 중단을 각각 시험하세요. 복구 절차는 남은 임시 대상, 완성된 최종 대상과 삭제되지 않은 원본, 프로세스 충돌 후 재시도를 안전하게 식별해야 합니다.

권한 변경, 같은 rename 반복, 오류 무시로 EXDEV를 “수정”하지 마세요. 요청한 원자적 계약이 마운트 경계를 넘었다는 증거로 보존하고, 강하고 약한 보장을 문서화한 워크플로를 선택하세요.

대상 임시 이름으로 복사하고 검증한 뒤 로컬 rename을 하는 흐름 도표
개념 일러스트: 안전한 파일시스템 간 게시는 대상 마운트에서 스테이징과 검증 후 로컬 rename을 수행합니다. Watch at Ease