GNU/Linux >> Znalost Linux >  >> Linux

Linux – Jak Linux přiděluje čísla inodů na souborových systémech, které nejsou založeny na inodech?

Toto je výstup ls -li příkaz na souborovém systému 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

1207 a 1208 jsou čísla inodů adresáře a souboru. Souborový systém VFAT však nemá koncept inodů.

Jak Linux přiřazuje čísla inodů souborům v souborovém systému, který nemá pojem inode?

Přijatá odpověď:

tl;dr:U virtuálních, volatilních nebo inodově agnostických souborových systémů jsou čísla inodů obvykle generována z monotónně se zvyšujícího 32bitového čítače při vytvoření inodu. Zbytek inodu (např. oprávnění) je vytvořen z ekvivalentních dat v základním souborovém systému nebo je nahrazen hodnotami nastavenými v době připojení (např. {uid,gid}= ), pokud žádný takový koncept neexistuje.

Chcete-li odpovědět na otázku v názvu (tj. abstraktně, jak Linux přiděluje čísla inodů pro souborový systém, který nemá koncept inodů), záleží na souborovém systému. U některých virtuálních nebo bezinodových souborových systémů je číslo inodu čerpáno v okamžiku vytvoření instance z get_next_ino bazén. To má však řadu problémů:

  1. get_next_ino() používá 32bitová čísla inodů i na 64bitovém jádře, kvůli staršímu zpracování pro 32bitové uživatelské prostředí bez _FILE_OFFSET_BITS=64;
  2. get_next_ino() je pouze globálně se zvyšující čítač používaný více souborovými systémy, takže riziko přetečení se ještě zvyšuje.

Problémy jako tento jsou jedním z důvodů, proč jsem minulý rok přesunul tmpfs od get_next_ino-backed inodů.

Z tohoto důvodu je tmpfs výjimka z většiny nestálých nebo „bezinodových“ formátů souborových systémů. Zásuvky, trubky, ramfs a podobně stále používají get_next_ino bazén k 5.11.

Pokud jde o vaši konkrétní otázku o souborových systémech FAT:fs/fat/inode.c je místo, kde se přidělují čísla inodů pro systémy FAT. Když se tam podíváme, vidíme fat_build_inode (zdroj):

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;
}

V podstatě to říká toto:

  1. Použijte zámek vytváření inodů FAT pro tento superblok.
  2. Zkontrolujte, zda na této pozici v superbloku již inode existuje. Pokud ano, odemkněte a vraťte tento inode.
  3. V opačném případě vytvořte nový inode.
  4. Získejte číslo inodu z iunique(sb, MSDOS_ROOT_INO) (více o tom za sekundu).
  5. Vyplňte zbytek inodu z ekvivalentních datových struktur FAT.

inode->i_ino = iunique(sb, MSDOS_ROOT_INO); zde se nastavuje číslo inodu. iunique (source) je fs-agnostická funkce, která poskytuje jedinečná čísla inodů pro daný superblok. Dělá to pomocí hašovací tabulky superblok + inode s monotónně rostoucím počítadlem:

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;
}

V tomto ohledu je velmi podobný dříve zmíněnému get_next_ino :pouze pro každý superblok místo toho, aby byl globální (jako pro potrubí, zásuvky a podobně), as nějakou základní ochranou proti kolizím na bázi hashovacích tabulek. Dokonce zdědí get_next_ino chování využívající 32bitová čísla inodů jako metodu, jak se vyhnout EOVERFLOW na starších aplikacích, takže pravděpodobně bude více souborových systémů, které budou potřebovat 64bitové opravy inodů (jako můj výše uvedený inode64 implementace pro tmpfs) v budoucnu.

Související:Linux – Jak připojit k souboru jako sudo?

Takže abych to shrnul:

  1. Většina virtuálních nebo bezinodových souborových systémů používá monotónně se zvyšující počítadlo pro číslo inodu.
  2. Tento čítač není stabilní ani pro systémy souborů bez inodů na disku*. Může se změnit bez dalších změn souborového systému při opětovném připojení.
  3. Většina souborových systémů v tomto stavu (kromě tmpfs s inode64 ) stále používají 32bitové čítače, takže při intenzivním používání je zcela možné, že čítač přeteče a vy můžete skončit s duplicitními inody.

* …ačkoli, abychom byli spravedliví, podle smlouvy to platí i pro souborové systémy, které dělají mít koncept inodu, když i_generation změny — v praxi je to méně pravděpodobné, protože číslo inodu často souvisí s jeho fyzickou polohou nebo podobně.


Linux
  1. Linux – Jak linuxové jádro zná hlavní a vedlejší čísla zařízení?

  2. Linux Setuid nefunguje?

  3. Jak uvolnit použití Inode?

  1. Jak přiřadit výstup příkazu Linux k proměnné

  2. Jak získat přístup k souborovým systémům Linux ve Windows 10 a WSL 2

  3. Jak funguje debugger v Linuxu?

  1. Inodes a souborový systém Linux

  2. Linux – Proč Setuid nefunguje?

  3. Linux – Jak lze zkontrolovat informace o struktuře adresářů souboru Unix/linux?