Re: Understanding reported block count for sparse files
Date: Wed, 23 Jul 2025 18:52:11 UTC
On Wed, Jul 23, 2025 at 12:33 PM Roman Bogorodskiy <novel@freebsd.org> wrote: > Hi, > > I'm porting a test from Linux, and this test checks the allocated block > count for the sparse file. Its expectation is that the block count > should be close to zero. > > To isolate things, it roughly does the following: > > Linux: > > $ truncate -s +52428800 test.raw > $ stat test.raw > File: test.raw > Size: 52428800 Blocks: 0 IO Block: 4096 regular file > Device: 252,0 Inode: 25218599 Links: 1 > Access: (0644/-rw-r--r--) Uid: ( 1000/ novel) Gid: ( 1000/ novel) > Context: unconfined_u:object_r:user_home_t:s0 > Access: 2025-07-23 14:20:31.640547511 -0400 > Modify: 2025-07-23 14:20:31.642105574 -0400 > Change: 2025-07-23 14:20:31.642105574 -0400 > Birth: 2025-07-23 14:20:31.640547511 -0400 > > It reports 0 blocks. > Filesystem here is xfs. > > FreeBSD: > > $ truncate -s +52428800 test.raw > $ stat -f "%z %k %b" test.raw > 52428800 32768 128 > > This reports 128 blocks. Filesystem here is UFS. > > What's reason behind this difference? > > Thanks, > Roman That "Blocks" figure comes from the "st_blocks" field, returned by VOP_STAT. It is entirely up to the file system what to put in that field. For example, if the file system is compressed, should st_blocks describe the blocks used before or after compression? ZFS reports blocks after compression, but IIRC btrfs reports blocks before compression. Both are legal. In this very specific case I can tell you why you are seeing this difference. UFS organizes files in a tree of indirect blocks. The tree can be up to 4 levels high, IIRC. So what's probably happening is that UFS is actually allocating all of the L2 and/or L1 blocks for the file, even though it's totally sparse, but not allocating any L0 blocks. If you really want to know exactly what's going on, we can probably explore the file in detail with filesystems/fuse-ufs. XFS, OTOH, is different. It's an extent-based file system. There's no such thing as indirect blocks. So when you create a huge but sparse file in XFS, all it needs to allocate is the inode. The number of metadata blocks is determined not so much by the file's size as by its fragmentation. It's technically possible, if the file is fully defragmented, to represent a 1 TB file with no metadata blocks except for the inode. But unlikely in practice. You could try using filesystems/xfuse or filesystems/lkl to see what that XFS file system looks like when mounted on FreeBSD, too. -Alan