コンピューティング · 実用ガイド

Linux の「Invalid cross-device link」:rename・copy・公開を選ぶ前にマウント境界を証明する

EXDEV はパス文字列の謎ではなく、契約上の警告です。呼び出し元のマウント名前空間で両方のパスを対応付け、原子的 rename が必要か判断し、別ファイルシステムへのコピーは移動元を消す前に移動先でステージングと検証を行います。

移動元のマウント ID 42 と宛先の ID 77 の間に EXDEV がある比較図
イラスト:パス移動を rename と見なす前に、呼び出し元の名前空間でマウント識別子を比較します。 Watch at Ease

Linux は rename が同じマウント済みファイルシステム内で移動を実行できないと EXDEV を返し、多くの場合「Invalid cross-device link」と表示されます。ディレクトリ名が似ていても、bind mount、コンテナボリューム、tmpfs、overlay 層、別ファイルシステムによって異なるマウント識別子になります。コードや権限を変える前に、失敗したプロセスと同じマウント名前空間から両パスを調べます。

別ファイルシステムへのフォールバックは rename の代用品ではありません。コピー、検証、成功後の移動元削除という別の処理です。読者に不完全な宛先を見せられない場合は、宛先ファイルシステム上の一時オブジェクトへ書き、フラッシュして検証し、同じ宛先マウント内で最終名へ rename します。ツールと宛先が実際に保持できるメタデータだけを約束し、マウントをまたぐ移動全体は原子的でないと明記します。

1. 失敗した操作と名前空間を記録する

実際の呼び出し元が使った移動元、宛先、プロセス ID、コンテナまたはサービスの文脈、返されたエラーを記録します。コンテナや非公開のマウント名前空間で失敗したなら、ホストのシェルだけで再現してはいけません。同じパス文字列でも別のマウント表を参照します。

単なる移設か、既存名の置換か、読者に all-or-nothing を約束する公開手順かも記録します。この要件で copy-and-delete を許容できるかが決まります。

2. 両方のパスをマウント識別子へ対応付ける

呼び出し元の名前空間から移動元と宛先ディレクトリに findmnt --target を実行します。別プロセスを調べる場合は、権限に応じて findmnt --task PID または /proc/PID/mountinfo を使います。ディレクトリの接頭辞ではなく、マウント ID、root、mount point、種類、source を比較します。

最終ファイルがまだなければ親ディレクトリを解決します。bind mount は同じ下位デバイスでも異なるマウント識別子を持つことがあり、rename(2) は同じファイルシステムが二か所にマウントされていてもマウント間 rename が拒否され得ると説明しています。

3. 操作に必要な保証を決める

一回の原子的な名前空間変更が必須なら、一時名と最終名を同じマウントに置き、そこで rename します。無条件に別ファイルシステムへのコピーを加えるのではなく、一時ディレクトリ、作業領域、ボリューム、公開ステージを再設定します。

一時的な重複と移動全体の非原子性を許容できるならコピー方式も正解ですが、保証内容を明示します。宛先の検証が終わるまで移動元を正本として扱います。

4. 宛先ファイルシステムでステージングして検証する

宛先ディレクトリに一意の一時名を作り、データをコピーし、耐久性方針に従って close と flush を行い、サイズまたは暗号学的ダイジェストを検証します。mode、owner、timestamp、ACL、拡張属性、symlink の同一性、sparse allocation はコピー方法によって失われ得ます。

検証後、宛先側の一時オブジェクトを最終名へ rename します。二つの名前が同じマウント上にあるため最後の rename は原子的にできます。元を削除する前に最終オブジェクトとアクセス方針を確認します。

5. EXDEV を隠さず、障害境界を試験する

コピー完了前、検証後、宛先側のローカル rename 後、移動元削除前の各中断を試験します。復旧手順は残った一時宛先、完成した最終宛先と未削除の元、プロセスクラッシュ後の再試行を安全に識別できる必要があります。

権限変更、同じ rename の再試行、エラーの握りつぶしで EXDEV を「修正」しないでください。要求した原子的契約がマウント境界を越えた証拠として残し、強弱の保証を記録した方式を選びます。

宛先の一時名へコピーして検証し、ローカル rename を行う流れの図
イラスト:安全な別ファイルシステム公開では、宛先マウントでステージングと検証をしてからローカル rename を行います。 Watch at Ease