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.