Short explanation
- "IO Block" in
stat
's output is the preferred number of bytes that the file system uses for reading and writing files. An IO Block is commonly 4096 bytes.
- "Blocks", on the other hand, counts how many 512-bytes blocks are allocated on disk for the file.
More detailed explanation
"IO Block" vs. "Blocks"
IO Block
"IO Block" is the preferred number of bytes that the file system uses for reading and writing files.
This number is fixed to 4096 bytes on my ext4 partition.
A block size of 4096 bytes is also the default for file systems between 512 MB and 4 TB. See man mke2fs.conf
, your /etc/mke2fs.conf
, and the documentation of the -T
option in man mkfs.ext4
.
Blocks
On the other hand, "Blocks" gives the number of 512-byte blocks allocated for the file on disk. Note that the blocks of stat
's "Blocks" have a different size than the blocks from "IO Block":
- number of bytes in a block of "IO Block": Defined by the file system. 4096 bytes in your and my case.
- number of bytes in a block of "Blocks": Always 512 bytes.
How do we know what "IO Block" and "Blocks" really refer to?
Digging through stat
's source code we find this line that creates the default output of stat
:
Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n\
Picking it apart:
Size: %-10s
: "Size:" prints the size of the file in bytes, with some padding using -10
.
Blocks: %-10b
: "Blocks" prints the value of placeholder %b
(with some padding). What's %b
? According to man 1 stat
:
%b number of blocks allocated (see %B)
Have a look at %B
:
%B the size in bytes of each block reported by %b
How many bytes are in a block denoted by "Blocks"?
stat --format="%B" ~/small_file
This prints "512". Alright, the block size of "Blocks" is 512 bytes.
On to the code that prints "IO Block":
IO Block: %-6o
: What's the placeholder %o
? Straight from man 1 stat
:
%o optimal I/O transfer size hint
Interesting! "IO Block" is short for "optimal I/O transfer size hint".
Running this on an ext4 file system:
stat --format="%o" ~/small_file
we learn the "IO Block" is 4096 bytes. That's quite a size difference:
- "IO Block": 4096 bytes
- "Blocks": 512 bytes
Putting it all together:
stat --format="File is %s bytes but needs %B*%b bytes on disk. Optimal I/O transfer size hint (alias IO Block): %o bytes" ~/small_file
Which prints the following in my case:
File is 116 bytes but needs 512*8 bytes on disk. Optimal I/O transfer size hint (alias IO Block): 4096 bytes
It's easy to make the mistake of thinking that the Blocks value counts the number of IO Blocks allocated on disk.
stat
the system call
From man 2 stat
we can learn more about the IO transfer size hint, also known as "IO Block":
The st_blksize field gives the "preferred" blocksize for efficient file system I/O. (Writing to a file in smaller chunks may cause an inefficient read-modify-rewrite.)
Also citing from man 2 stat
that describes the field st_blocks
which is useful to understand stat
's "Blocks":
This field indicates the number of blocks allocated to the file, in 512-byte units.
More examples with stat
Here is shortened example output of stat ~/small_file
:
File: /home/mb/small_file
Size: 116 Blocks: 8 IO Block: 4096 regular file
// Rest omitted
Size: 116
means there are 116 bytes of data in this file. But it doesn't tell us how many bytes are used to store this file on disk. That's what "Blocks" is for.
Blocks: 8
means this file takes up 8 * 512 = 4096 bytes on disk. Given that the file only has 116 bytes of data, this is a little wasteful. But we can't use fewer bytes since the block size of ext4 on my system is 4096 bytes. How wasteful? Let's calculate: 116 / 4096 * 100 ≈ 2.8
meaning only about 2.8% of the allocated bytes are actually used for storing the file's data.
IO Block: 4096
means the preferred number of bytes that are read or written from the disk at once.
Another example with a slightly larger file, stat ~/larger_file
:
File: /home/mb/larger_file
Size: 91246 Blocks: 184 IO Block: 4096 regular file
// Rest omitted
Size: 91246
tells us the number of bytes in this file, independent of our file system and the number of bytes it physically occupies on disk.
Blocks: 184
lets us calculate the number of bytes this file physically occupies on disk: 184 * 512 = 94208 bytes. How many of those allocated bytes are used for actually storing larger_file
's data? 91246 / 94208 * 100 ≈ 96.9
. About 96.6% is the file's data, that's much more efficient compared to our previous example with ~/small_file
.
Changing value of "IO Block"
I doubt you can change the value of "IO Block" of an existing file system. Here's a discussion on that.
In case you are creating a new file system, there's the -b
option that specifies the block size in bytes.
mkfs.ext4 -b 2048 /dev/sdb1
From the manual:
Valid block-size values are 1024, 2048 and 4096 bytes per block.