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

Konstantin Belousov <[email protected]> Sun, 2 Aug 2026 16:54:43 +0300
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
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.