预分配空间不立即占用物理块,df仅显示实际已用空间;判断文件是否预分配需用ls -lsh、filefrag -v和stat对比逻辑大小与实际块数;lvm thin pool和reflink等机制需分层验证真实占用。

预分配空间(如稀疏文件、LVM逻辑卷、XFS的reflink、ext4的fallocate预留)在Linux中不会立即占用物理块,df 显示的是文件系统级“已用/可用”空间,但无法反映单个文件的预分配状态——它只看实际写入的数据块。要查预分配空间利用率详情,必须分层确认:文件系统是否支持预分配、文件是否真被预分配、底层块设备是否已真正落盘。
怎么判断一个文件是否用了预分配(fallocate / truncate)
预分配不等于写入数据,fallocate -l 10G file 或 truncate -s 10G file 都会快速创建一个“看起来很大”的文件,但可能全是空洞(hole)。验证方法:
-
ls -lsh file:左边数字是实际占用的磁盘块数(KB),右边是逻辑大小。若两者差距极大(如0 10G),说明是纯稀疏文件,未占物理空间 -
filefrag -v file:显示每个逻辑块是否映射到物理块。输出中若有大量0: 0..N: 0-0: 0: hole行,代表对应区间是空洞 -
stat file:关注Blocks:字段(512-byte units),对比Size:。例如Size: 10737418240(10G)但Blocks: 0,即完全未分配物理块
为什么 df 不显示预分配空间的“潜在占用”
df 统计的是文件系统元数据中已分配的块(used)和空闲块(avail),而预分配操作本身不分配块,只是修改inode的i_size。所以:
-
fallocate -l 10G file后,df -h的Use%不变 - 但当程序开始向该文件写入真实数据时,块才被分配,
df的Use%才会上升 - 某些文件系统(如XFS)支持
fallocate --keep-size或--zero-range,这些操作可能触发部分块分配,需结合filefrag观察
查看LVM逻辑卷的预分配与实际使用差异
LVM中,LV可被创建为稀疏(thin-provisioned)或厚置备(thick)。关键命令:
-
lvs -o +lv_attr,lv_size,data_percent,metadata_percent:对 thin pool,data_percent表示已写入数据占比;lv_attr中t表示 thin LV,w表示 thick -
lvs -o +stripes,stripesize:厚置备LV无“预分配利用率”概念,其lv_size就是固定占用的块设备空间 - thin pool 本身也是文件系统级对象,它的空间由
df -h /dev/mapper/poolname显示,但该值反映的是pool所在块设备的使用率,不是LV的逻辑大小
容易忽略的坑:reflink 和 CoW 文件系统的“伪预分配”
XFS(with reflink)或 Btrfs 中,cp --reflink=always 创建的文件看似复制了大小,但底层共享数据块。此时:
-
du -sh file显示的是该文件独占的数据块大小(可能极小),不是逻辑大小 -
df不会因 reflink 操作变化,除非后续写时发生 CoW 分配新块 - 用
xfs_info /mount/point确认是否启用reflink;Btrfs 用btrfs filesystem usage /mount/point查看 data chunk 实际分配量
预分配空间的“利用率”本质上是个语义陷阱:它没有统一指标。你得先明确问的是“这个文件逻辑上多大但物理上占多少”(ls -lsh + filefrag),还是“这个thin pool还有多少空间能被LV消耗”(lvs),抑或“reflink文件实际复用了多少块”(btrfs filesystem usage)。混用工具会得到矛盾结果。











