1 TB 的 ext4 盘上全存 1 字节文件,只能放 67108864 个——能存的空间还剩一大半,先卡住的是 inode。分水岭正好是 16 KB:比它小的先撞 inode,比它大的先撞空间。
7.2 讲了元数据也占地方,这一节算清它的上限:盘能被两种配额卡住,一种管字节,一种管文件个数。
一、两道配额
ext4 在格式化的时候就定了两个数。
① 块大小,默认 4 KB——限制【总共能存多少字节】。② inode 密度,默认每 16 KB 空间配 1 个——限制【总共能有几个文件】。
算一下 1 TB 的盘:块 268435456 个;inode 67108864 个。
这两道配额是【各自独立】的,哪个先用完,哪个就把你挡住。而用完时的报错是同一句——No space left on device。
这就是最坑的地方:报错说【空间不够】,其实可能是【inode 不够】。
二、16 KB 那个数是怎么来的
把两道配额除一下就看出来了。 一个文件占的块数 = 大小 ÷ 4 KB 向上取整,所以它的【空间成本】随大小线性长。它的【inode 成本】却恒等于 1。 平均每个文件 16 KB 时,两道配额刚好同时用完。 比 16 KB 小——inode 成本占主导,先撞 inode。比 16 KB 大——空间成本占主导,先撞空间。 16 KB 这个数不是随便定的,它是对【典型文件大小】的一个估计。做文件系统的人要猜用户存什么,猜小了 inode 不够用,猜大了 inode 白占空间。 猜错的场景很明显:拿 ext4 当【几百万张缩略图】的仓库(每张 20 KB 上下),或者拿它当【几十万个小文本】的代码仓,都会在空间还剩一半的时候写不进去。
三、为什么 1 字节和 4 KB 是一样的
因为按块分配。1 字节、100 字节、4 KB 整——三种大小都占满 1 块。 所以从【能放几个】这个角度看,它们完全等价:都是 268435456 个。而 inode 只够 67108864 个,于是先卡住。 反过来,1 MB 的文件要 256 块,空间只够放 1048576 个,而 inode 还够 67108864 个——空间先撞。 100 MB 的文件更极端:只要 10485 个就把盘填满,inode 一个都没用掉零头。 这张表最有用的地方是【判断你的场景属于哪一边】,不用记住具体数字。 平均文件小于 16 KB → 关心 inode;大于 16 KB → 关心空间。
四、所以两条命令都要看
df -h 看空间,df -i 看 inode。两条一起看,才知道是哪一道配额先到。
真遇到了怎么办?
① 删文件——但注意 inode 释放要等所有打开它的进程退出。② 加固:ext4 在格式化时可以把 inode 密度调大(mkfs.ext4 -i 8192 表示每 8 KB 一个)。③ 换文件系统——XFS 是动态分配 inode 的,没有这个上限(代价是 inode 本身占空间,且不能预留)。
还有一个隐蔽的坑:目录本身也吃 inode,也占块。一个目录里塞一千万个文件,那个目录文件会变得巨大,而且 rm -rf 要跑很久。
五、动手 Demo:容量限制——盘没满却写不进去的两种情形
这一节不算实际磁盘,只把 ext4 的两道配额放在一张表上算一遍, 看不同大小的文件分别先撞哪一边。
GB = 1024 ** 3
KB = 1024
MB = 1024 * 1024
disk = 1024 * GB # 1 TB
blk = 4 * KB # 块 4 KB
inode_ratio = 16 * KB # 每 16 KB 一个 inode
nblk = disk // blk # 268435456
nino = disk // inode_ratio # 67108864
for label, avg in (("1B~4KB", 1), ("16KB", 16 * KB),
("64KB", 64 * KB), ("1MB", MB),
("100MB", 100 * MB)):
per_file = max(1, (avg + blk - 1) // blk)
by_space = nblk // per_file
by_inode = nino
lim = min(by_space, by_inode)
who = "inode" if by_inode < by_space else \
("space" if by_space < by_inode else "both")
print(label, per_file, lim, who)
实跑输出:
--------------------------------------------------------------------
容量限制——盘没满却写不进去的两种情形
--------------------------------------------------------------------
① 先看清两道配额
**ext4 默认两个数**:**块 4 KB;每 16 KB 空间配 1 个 inode。**
**前者限制【总共能存多少字节】,后者限制【总共能有几个文件】。**
配额 算法 数量
-------------------------------------------
数据块 1 TB ÷ 4 KB 268435456 块
inode 1 TB ÷ 16 KB 67108864 个
② 两种文件大小,谁先耗完
文件大小 占几块 空间够几个 inode 够几个 上限 卡在哪
----------------------------------------------------------------------------------------------
1 字节 ~ 4 KB 1 268435456 个 67108864 个 67108864 个 inode 先耗尽
16 KB 4 67108864 个 67108864 个 67108864 个 同时耗尽
64 KB 16 16777216 个 67108864 个 16777216 个 空间先耗尽
1 MB 256 1048576 个 67108864 个 1048576 个 空间先耗尽
100 MB 25600 10485 个 67108864 个 10485 个 空间先耗尽
**分水岭正好是 16 KB。**
**文件比 16 KB 小 → inode 先不够**
(**能存的空间还剩一大半,就写不进去了**);
**文件比 16 KB 大 → 空间先不够**(inode 还剩一堆)。
**注意 1 字节与 4 KB 那一行一模一样**:
**因为按块分配,1 个字节也要占满一整块。**
**这就是 ext4 那个 16 KB 的来历**——
**它不是随便定的,是按【典型文件大小】估出来的。**
**所以拿 ext4 当【存几百万张缩略图】的仓库会踩坑**:
**`df` 说还剩一半空间,`df -i` 说 inode 用完了。**
📋 **Linux 上这两条命令必看**:`df -h`(空间)、`df -i`(inode)。
**出现【No space left on device】但 `df -h` 还有空间,**
**九成是 inode 用完了。**
16 KB 那一行两边正好相等,这就是分水岭。比它小的都是 inode 先耗尽,比它大的都是空间先耗尽。 注意 1 字节与 4 KB 那两行完全等价——因为按块分配,1 个字节也要占满一整块。 这个模型是【算】出来的,不是【测】出来的:它假设的是 ext4 的默认参数。换成 XFS 就没有 inode 上限这一说了。
📋 Linux 上两条命令必看:df -h(空间)、df -i(inode)。
📋 看自己的 inode 密度:tune2fs -l /dev/sda1 | grep -i inode。
30 秒实验
df -i看一眼你机器的 inode 用了百分之几,和df -h比一比。tune2fs -l /dev/sda1 | grep -i "inode count",算出自己的实际密度。- 在一个目录下建 5 万个空文件,看
ls与rm -rf各要多久。
常见误区
- 【No space left on device 一定是没空间了】。很可能是 inode 用完了——先
df -i再说。 - 【删了文件 inode 就回来了】。只要有进程还开着它,inode 与块都不释放;
lsof | grep deleted能找到这种【看不见的占用】。 - 【inode 数可以随便改】。它在格式化时就定了,之后不能扩(只能备份、重格式化、恢复)。
自测三问(点开对答案)
1. 为什么 1 字节的文件和 4 KB 的文件能放的个数一样? —— **因为按块分配**:**两者都占满 1 个 4 KB 块**,**从【能放几个】的角度完全等价。** 2. 平均文件大小 16 KB 意味着什么? —— **空间配额与 inode 配额正好同时用完**。**比它小就先撞 inode,比它大就先撞空间。** 3. 为什么 XFS 没有 inode 不够的问题? —— **因为它动态分配 inode**,**用多少给多少**;**代价是 inode 本身占空间,且不能事先预留。**- ☐ 7.4 文件系统不一致
相关笔记
- 数据与元数据 — 元数据为什么也占地方
- 文件系统不一致 — 元数据写坏了会怎样
- 文件系统不一致的对策 — 三道防线
- 🐧 Linux是怎样工作的 · 索引