ZFS存储池已用空间与实际内容差距悬殊,求原因及回收方案
ZFS存储池已分配空间与实际占用差异排查及空间回收
问题背景
基于两块1TB镜像硬盘创建名为zoo的ZFS存储池,用于承载4个FreeBSD 12.1 jail。当前出现存储池已分配空间与实际文件占用严重不符的问题:
ZFS数据集统计
[develop@silversurfer /mnt/zoo]$ zfs list -r zoo NAME USED AVAIL REFER MOUNTPOINT zoo 829G 69.9G 996M /mnt/zoo zoo/beyond 807G 69.9G 114G /mnt/zoo/beyond zoo/officetemplates 48.8M 69.9G 46.2M /mnt/zoo/officetemplates zoo/overflow 152K 89.9G 96K /mnt/zoo/overflow
其中overflow是设置了20GB最小容量(预留空间)的空数据集,其他数据集无固定大小或配额。曾两次因磁盘满错误,通过缩小overflow的预留空间临时解决。
文件系统实际占用统计
[develop@silversurfer /mnt/zoo]$ ls -al total 75 drwxrwxrwx 7 root wheel 6 Nov 18 14:46 . drwxr-xr-x 5 root wheel 5 Nov 12 2021 .. dr-xr-xr-x+ 3 root wheel 3 Sep 3 2019 .zfs drwxrwxr-x 7 develop 2B 6 Nov 17 2021 beyond drwxrwx--- 6 www 2B 75 May 23 17:30 officetemplates drwxrwxrwx 2 root wheel 2 Nov 1 10:32 overflow drwxrwxr-x 4 popeye 2B 8 Nov 13 10:37 scans [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo 117G /mnt/zoo [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo/.zfs 4.9G /mnt/zoo/.zfs [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo/beyond 116G /mnt/zoo/beyond [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo/officetemplates 45M /mnt/zoo/officetemplates [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo/scans 994M /mnt/zoo/scans [develop@silversurfer /mnt/zoo]$ sudo du -hs /mnt/zoo/overflow 512B /mnt/zoo/overflow
核心疑问:zfs list显示zpool已分配829GB空间,但实际文件仅占用117GB,两者的差值空间被什么占用?如何回收?
原因分析
从zfs list输出看,zoo/beyond的USED(807G)远大于REFER(114G),这是差值的主要来源。这种情况通常由以下因素导致:
- 未清理的快照:ZFS快照会保留数据集在快照创建时刻的所有数据,包括后续删除的文件,这会导致
USED持续累积,而REFER仅反映当前活跃文件的大小。 - 克隆数据集:基于快照创建的克隆会共享快照数据,即使克隆本身数据量小,也会占用快照对应的空间。
- 预留空间(Reservation):如果数据集设置了超出实际使用的预留空间,这部分空间会被标记为已分配,无法被其他数据集使用。
- 延迟释放的块:ZFS删除文件后,不会立即释放磁盘块,而是等待一段时间或在scrub后回收,但一般不会产生如此大的差值。
排查与回收步骤
1. 排查快照占用
执行以下命令列出所有快照及其占用空间:
zfs list -t snapshot -r zoo
快照的USED列会显示该快照单独占用的空间(不包括与其他快照共享的部分),累计所有快照的占用即可找到大部分差值来源。
回收方法:删除不需要的快照,命令格式为:
# 删除单个快照 zfs destroy zoo/beyond@<快照名称> # 批量删除某前缀的快照 zfs destroy -r zoo/beyond@<快照前缀>
2. 排查克隆数据集
执行以下命令列出所有克隆:
zfs list -t clone -r zoo
克隆依赖于父快照,若克隆不再使用,需先删除克隆,再删除对应的父快照才能释放空间。
回收方法:
# 删除克隆 zfs destroy <克隆数据集名称> # 再删除对应的父快照 zfs destroy <父快照名称>
3. 检查并调整预留空间
执行以下命令查看所有数据集的预留和配额设置:
zfs get reservation,quota -r zoo
重点关注overflow的reservation值,确认是否还有未完全取消的预留;同时检查zoo/beyond是否被意外设置了预留。
回收方法:取消不必要的预留空间:
zfs set reservation=0 zoo/overflow # 若其他数据集有不合理预留,同样执行上述命令
4. 强制回收延迟释放空间
若存在未立即释放的磁盘块,可执行以下操作加速回收:
# 执行存储池 scrub,修复并标记可回收的块 zpool scrub zoo # 等待scrub完成后,执行同步 zfs sync
scrub完成后,ZFS会自动回收可释放的块,可通过再次执行zfs list -r zoo确认空间变化。
内容的提问来源于stack exchange,提问作者patmin
相关产品推荐
相关产品推荐

