Yi Zhenfei
Yi Zhenfei

Reputation: 166

What do f_bsize and f_frsize in struct statvfs stand for?

In struct statvfs (which is used by the statvfs syscall), there are two fields: f_bsize and f_frsize. What exactly do they stand for? Or to be more specific, if I need to get the logical block size of the filesystem, which one should I use?

It is very confusing, because in the Linux man page, it is said:

unsigned long f_bsize; /* file system block size */
unsigned long f_frsize; /* fragment size */

It seems like f_bsize is the logical block size which I need, while in the man page of macOS, it is said:

f_frsize The size in bytes of the minimum unit of allocation on this file system. (This corresponds to the f_bsize member of struct statfs.)
f_bsize The preferred length of I/O requests for files on this file system. (Corresponds to the f_iosize member of struct statfs.)

It seems like f_frsize is the logical block size, finally I checked the POSIX standards, and here is the specification:

unsigned long f_bsize File system block size.
unsigned long f_frsize Fundamental file system block size.

I have googled for a while and failed to find the definition of the "Fundamental file system block size. Is there anybody who can help?

Upvotes: 9

Views: 5790

Answers (2)

Steve Lau
Steve Lau

Reputation: 1033

Just cite the The Linux Programming Interface (Page 276) as a supplement:

For most Linux file systems, the values of f_bsize and f_frsize are the same. However, some file systems support the notion of block fragments, which can be used to allocate a smaller unit of storage at the end of the file if a full block is not required. This avoids the waste of space that would otherwise occur if a full block was allocated. On such file systems, f_frsize is the size of a fragment, and f_bsize is the size of a whole block. (The notion of fragments in UNIX file systems first appeared in the early 1980s with the 4.2BSD Fast File System, described in [McKusick et al., 1984].)

Upvotes: 4

Shawn
Shawn

Reputation: 731

It will depend on your operating system and file system. On linux, f_frsize is rarely (if ever) going to be different than f_bsize - quickly searching the kernel source finds only one real use case (in the nfs server code) where f_frsize is set, and it comes with the following notes:

/*
 * Current versions of glibc do not correctly handle the
 * case where f_frsize != f_bsize.  Eventually we want to
 * report the value of wtmult in this field. 
 * (wtmult is presumed to be the nfs server's disk block size)
 */
buf->f_frsize = dentry->d_sb->s_blocksize;

/*
 * On most *nix systems, f_blocks, f_bfree, and f_bavail
 * are reported in units of f_frsize.  Linux hasn't had
 * an f_frsize field in its statfs struct until recently,
 * thus historically Linux's sys_statfs reports these
 * fields in units of f_bsize.
 */

And in fs/statfs.c, frsize will be set to bsize if a given file system driver does not set it:

if (retval == 0 && buf->f_frsize == 0)
    buf->f_frsize = buf->f_bsize;

'logical' block size is the size in bytes of the blocks on the file system (vs physical block size on a hard drive for instance), and this is what is indicated by f_bsize.

It seems to me that the POSIX specification is intentionally vague, and it's up to each file system to determine/document the exact meaning of the two fields. I would personally take 'fundamental file system block size' to mean the size of the smallest amount of data that a single file can allocate, a kind of base unit of the file system.

Maybe I've gone on a bit of a tangent though -

Perhaps there is some confusion due to statvfs vs statfs, which are different functions/structures, both of which have members with names f_frsize and f_bsize, which don't have the same meaning across both structures.

What the MacOS documentation is saying is that the statvfs.f_frsize has the same meaning as statfs.f_bsize, and statvfs.f_bsize is likewise equivalent to statfs.iosize.

So you can use statfs.f_bsize or statvfs.f_frsize to determine the logical block size of a file system. statvfs is the newer and POSIX standard way, though some systems recommend against its usage.

Upvotes: 9

Related Questions