tok*_*a-n 15 linux filesystems
这是该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
Run Code Online (Sandbox Code Playgroud)
1207和1208是目录和文件的 inode 编号。但是,VFAT 文件系统没有 inode 的概念。
Linux 如何为没有 inode 概念的文件系统上的文件分配 inode 编号?
Chr*_*own 32
tl;dr:对于虚拟、易失或与 inode 无关的文件系统,inode 编号通常在创建 inode 时从单调递增的 32 位计数器生成。inode 的其余部分(例如权限)是从底层文件系统中的等效数据构建的,或者{uid,gid}=如果不存在这样的概念,则替换为在安装时设置的值(例如)。
要回答标题中的问题(即抽象地说,Linux 如何为没有 inode 概念的文件系统分配 inode 编号),这取决于文件系统。对于某些虚拟或无节点文件系统,在实例化时从get_next_ino池中提取 inode 编号。但是,这有很多问题:
get_next_ino()即使在 64 位内核上也使用 32 位 inode 编号,这是由于 32 位用户空间的遗留处理而没有_FILE_OFFSET_BITS=64;get_next_ino() 只是多个文件系统使用的全局递增计数器,因此溢出的风险会进一步增加。像这样的问题是我去年将 tmpfs 从 get_next_ino 支持的 inode 移开的原因之一。
出于这个原因,tmpfs 特别是大多数易失性或“无节点”文件系统格式的例外。get_next_ino从 5.11 开始,套接字、管道、ramfs 等仍然使用池。
至于您关于 FAT 文件系统的具体问题:fs/fat/inode.c是为 FAT 邪恶系统分配 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;
}
Run Code Online (Sandbox Code Playgroud)
这基本上是这样说的:
iunique(sb, MSDOS_ROOT_INO)(稍后会详细介绍)。inode->i_ino = iunique(sb, MSDOS_ROOT_INO);是在这里设置 inode 编号的地方。iunique( source ) 是一个 fs 不可知函数,它为给定的超级块提供唯一的 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;
}
Run Code Online (Sandbox Code Playgroud)
在这方面,它与前面提到的非常相似get_next_ino:只是每个超级块而不是全局的(如管道、套接字等),并且具有一些基于哈希表的基本冲突保护。它甚至继承了get_next_ino使用 32 位 inode 编号作为尝试避免遗留应用程序上的 EOVERFLOW 的方法的行为,因此可能会有更多的文件系统需要 64 位 inode 修复(如我前面提到inode64的 tmpfs 实现)未来。
所以总结一下:
inode64)仍在使用 32 位计数器,因此大量使用时,计数器完全有可能溢出,最终可能会出现重复的 inode。* ...虽然,公平地说,即使对于在更改时确实具有 inode 概念的文件系统,这也是正确的i_generation- 在实践中不太可能发生,因为 inode 编号通常与其物理位置相关,或者相似的。