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

Mark Millard <[email protected]> Sun, 2 Aug 2026 07:48:08 -0700
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
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.


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