Linuxは、inodeベースではなくファイルシステムからinode番号をどのように割り当てますか?

Linuxは、inodeベースではなくファイルシステムからinode番号をどのように割り当てますか?

ls -liこれは VFAT ファイルシステムへのコマンドの出力です。

% ls -li
合計 736
1207 drwxr-xr-x 3 root root  16384  3月 10 10:42 efi
1208 -rwxr-xr-x 1 root root 721720  3月 22 14:15 kernel.bin

12071208ディレクトリとファイルのinode番号。ただし、VFATファイルシステムにはinodeの概念はありません。

Linuxは、inodeの概念を持たないファイルシステムのファイルにinode番号をどのように割り当てますか?

ベストアンサー1

tl;dr: 仮想、揮発性、または inode 独立ファイルシステムの場合、inode 番号は通常、inode が生成されると単調に増加する 32 ビットカウンタで生成されます。残りのinode(権限など)は、基本ファイルシステムの同等のデータから構築された場合、または{uid,gid}=そのような概念が存在しない場合は、インストール時に設定された値(たとえば)に置き換えられます。


タイトルの質問(つまり、抽象的にLinuxがinodeの概念を持たないファイルシステムにinode番号を割り当てる方法)に答えるには、ファイルシステムによって異なります。一部の仮想またはinodelessファイルシステムでは、inode番号はget_next_inoインスタンス化時にプールから取得されます。しかし、ここには多くの問題があります。

  1. get_next_ino()32ビットinode番号は64ビットカーネルでも使用されます。なぜなら、従来の32ビットユーザー領域処理はそうではないからです_FILE_OFFSET_BITS=64
  2. get_next_ino()複数のファイルシステムで使用されるグローバル増分カウンタであるため、オーバーフローのリスクがさらに増加し​​ます。

この質問も私の理由の一つです。昨年、tmpfsはget_next_inoがサポートしているinodeから離れていました。

したがって、tmpfsは、ほとんどの揮発性または「ノードレス」ファイルシステム形式の例外です。get_next_ino5.11以降、ソケット、パイプ、ランプなどは依然としてこのプールを使用しています。


FATファイルシステムに関する具体的な質問は、fs/fat/inode.cFATファイルシステムに割り当てられたinode番号はどこですか?内部を見るとfat_build_inode源泉):

struct inode *fat_build_inode(struct super_block *sb,
                              struct msdos_dir_entry *de, loff_t i_pos)
{
        struct inode *inode;
        int err;

        fat_lock_build_inode(MSDOS_SB(sb));
        inode = fat_iget(sb, i_pos);
        if (inode)
                goto out;
        inode = new_inode(sb);
        if (!inode) {
                inode = ERR_PTR(-ENOMEM);
                goto out;
        }
        inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
        inode_set_iversion(inode, 1);
        err = fat_fill_inode(inode, de);
        if (err) {
                iput(inode);
                inode = ERR_PTR(err);
                goto out;
        }
        fat_attach(inode, i_pos);
        insert_inode_hash(inode);
out:
        fat_unlock_build_inode(MSDOS_SB(sb));
        return inode;
}

これは基本的に次のように言います。

  1. このスーパーブロックのFAT inode生成ロックを取得します。
  2. スーパーブロックのこの位置にインデックスノードがすでに存在することを確認してください。そうであれば、インデックスノードはロック解除され、返されます。
  3. それ以外の場合は、新しいインデックスノードを作成します。
  4. inode番号を取得しますiunique(sb, MSDOS_ROOT_INO)(後で詳しく説明します)。
  5. 同等のFATデータ構造から残りのinodeを埋めます。

inode->i_ino = iunique(sb, MSDOS_ROOT_INO);ここで inode 番号を設定します。iunique源泉)は、与えられたスーパーブロックに対して一意のinode番号を提供するファイルシステムに依存しない関数です。これは、スーパーブロック+ inodeベースのハッシュテーブルと単調に増加するカウンタを使用してこれを行います。

ino_t iunique(struct super_block *sb, ino_t max_reserved)
{
        static DEFINE_SPINLOCK(iunique_lock);
        static unsigned int counter;
        ino_t res;

        rcu_read_lock();
        spin_lock(&iunique_lock);
        do {
                if (counter <= max_reserved)
                        counter = max_reserved + 1;
                res = counter++;
        } while (!test_inode_iunique(sb, res)); /* nb: this checks the hash table */
        spin_unlock(&iunique_lock);
        rcu_read_unlock();

        return res;
}

この点で、これは前述のものと非常によく似ていますget_next_ino。グローバル(パイプ、ソケットなど)ではなくスーパーブロックごと、基本ハッシュテーブルに基づくいくつかの衝突防止保護機能があります。get_next_ino従来のアプリケーションで EOVERFLOW を試して防止する方法として 32 ビット inode 番号を使用する動作も継承するため、inode64今後は 64 ビット inode 修正 (前述の tmpfs 実装など) が必要なファイルシステムが増える可能性があります。

結論として:

  1. ほとんどの仮想またはinodelessファイルシステムは、単調に増加するカウンタを使用してinode番号を表します。
  2. このカウンタは、オンディスクノードレスファイルシステム*の場合でも不安定です。ファイルシステムに他の変更なしで再マウントすると、変更されることがあります。
  3. この状態のほとんどのファイルシステム(tmpfsを除くinode64)はまだ32ビットカウンタを使用しているため、過度に使用するとカウンタがオーバーフローし、冗長inodeが発生する可能性があります。

* ...公平に言えば、これは次のファイルシステムの場合でも契約上適用されます。するinodeが変更されたときの概念があります。i_generationinode 番号は通常、物理的な場所または同様のものに関連しているため、実際には発生する可能性はありません。

おすすめ記事