🐧 第七章 文件系统
📄 一句话概括

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 秒实验

  1. df -i 看一眼你机器的 inode 用了百分之几,和 df -h 比一比。
  2. tune2fs -l /dev/sda1 | grep -i "inode count",算出自己的实际密度。
  3. 在一个目录下建 5 万个空文件,看 ls 与 rm -rf 各要多久。

常见误区

  1. 【No space left on device 一定是没空间了】。很可能是 inode 用完了——先 df -i 再说。
  2. 【删了文件 inode 就回来了】。只要有进程还开着它,inode 与块都不释放;lsof | grep deleted 能找到这种【看不见的占用】。
  3. 【inode 数可以随便改】。它在格式化时就定了,之后不能扩(只能备份、重格式化、恢复)。
自测三问(点开对答案) 1. 为什么 1 字节的文件和 4 KB 的文件能放的个数一样? —— **因为按块分配**:**两者都占满 1 个 4 KB 块**,**从【能放几个】的角度完全等价。** 2. 平均文件大小 16 KB 意味着什么? —— **空间配额与 inode 配额正好同时用完**。**比它小就先撞 inode,比它大就先撞空间。** 3. 为什么 XFS 没有 inode 不够的问题? —— **因为它动态分配 inode**,**用多少给多少**;**代价是 inode 本身占空间,且不能事先预留。**

相关笔记