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