Re: [Question] st_blocks of shm is number of pages, not 512B blocks
Konstantin Belousov <[email protected]> Sun, 2 Aug 2026 19:27:11 +0300
| Newsgroups | gmane.os.freebsd.devel.file-systems |
|---|---|
| Message-ID | <[email protected]> |
On Sun, Aug 02, 2026 at 09:12:25AM -0700, Mark Millard wrote:
> 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.
https://reviews.freebsd.org/D58592