Re: [Question] st_blocks of shm is number of pages, not 512B blocks

Mark Millard <[email protected]> Sun, 2 Aug 2026 09:12:25 -0700
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
On 8/2/26 07:48, Mark Millard wrote:
> On 8/2/26 06:54, Konstantin Belousov wrote:
>> On Sun, Aug 02, 2026 at 08:42:36PM +0900, David Timber wrote:
>>> Hi!
>>>
>>> Just out of curiosity, when you do ...
>>>
>>> 	struct stat st;
>>> 	int fd;
>>>
>>> 	fd = shm_open(...);
>>> 	ftruncate(fd, ...);
>>> 	fstat(fd, &st);
>>>
>>> 	printf("%lld\n", st.st_blocks);
>>>
>>> you get st.st_blocks as the number of system memory pages allocated, not
>>> the usual 512-byte unit. Because, in sys/kern/uipc_shm.c:
>>>
>>> static int
>>> shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred)
>>> {
>>> 	...
>>> 	if (shm_largepage(shmfd)) {
>>> 		sb->st_blocks = shmfd->shm_object->size /
>>> 		    (pagesizes[shmfd->shm_lp_psind] >> PAGE_SHIFT);
>>> 	} else {
>>> 		sb->st_blocks = shmfd->shm_pages;
>>> 	}
>>>
>>> I was a bit confused when I discovered this. FreeBSD is the only BSD
>>> that exhibit this behaviour.
>>>
>>> I'm just wondering if there was any case where getting the number of
>>> pages is better? Was there a historic precedence? If so, I think this
>>> behaviour has to be documented somewhere.
>>>
>>> The showcases:
>>>
>>>   * https://github.com/dxdxdt/gists/blob/09b721a50fa2811846e31a986e9b1bdc0f0d35a1/writeups/mmap-magic/mmap-arena-test.c#L108
>>>   * https://github.com/dxdxdt/gists/actions/runs/30700765339/job/91371261488
>>
>> The st_blksize field is set to PAGE_SIZE.  This should give enough hint
>> for the multiplier of st_blocks.
>>
>> The page size as st_blocks multiplier is natural because shm is allocated
>> in pages.  I wanted to return the number of large pages for st_blocks for
>> the largepage shmfds as well, but somebody argued against it AFAIR.
>>
>> FreeBSD' uipc_shm.c was developed independently of other BSDs.
>>
>>
> 
> # man 2 fstat reports otherwise:
> 
> . . .
>     st_blksize  Optimal I/O block size for the file.
> 
>      st_blocks   Actual number of blocks allocated for the file in 512-byte
>                  units.  As short symbolic links are stored in the
> inode, this
>                  number may be zero.
> . . .
> 
> Looks like the behavior needs a documentation update if it stays as-is.
> 
> 

I decided to look at POSIX-2024 to see how different FreeBSD is and in
what way:

QUOTE of rationale text:
The unit for the st_blocks member of the stat structure is not defined
within POSIX.1-2024. In some implementations it is 512 bytes. It may
differ on a file system basis. There is no correlation between values of
the st_blocks and st_blksize, and the f_bsize (from <sys/statvfs.h>)
structure members.

Traditionally, some implementations defined the multiplier for st_blocks
in <sys/param.h> as the symbol DEV_BSIZE.
END QUOTE

Varying on other than a file system basis is not indicated. Thus a need
for documentation for other FreeBSD-specific context-types that leads to
variations.

This also appears to make inferring block size units via referencing
st_blksize solidly non-POSIX. Thus a need for documentation of what
FreeBSD has its principles of operation for the relationship.


-- 
===
Mark Millard
marklmi at yahoo.com