Skip to content

Commit cd87e8a

Browse files
committed
fs: expose frsize field in statfs results
Node.js statfs() exposes bsize (optimal I/O block size) but not frsize (fundamental filesystem block size). Per POSIX, block counts (blocks, bfree, bavail) are in units of frsize, not bsize. libuv already reads f_frsize from the kernel — it was simply not mapped to JavaScript. On most native filesystems bsize == frsize, so the omission was harmless. However, on FUSE mounts (e.g. Docker Desktop on macOS with VirtioFS or gRPC FUSE), they can differ by orders of magnitude (bsize=2MiB vs frsize=16KiB), causing applications that compute disk space as bsize*blocks to report wildly inflated values. This commit adds the frsize property to the StatFs object returned by fs.statfs(), fs.statfsSync(), and fsPromises.statfs(), in both normal and bigint modes.
1 parent bdf75a6 commit cd87e8a

File tree

6 files changed

+25
-4
lines changed

6 files changed

+25
-4
lines changed

doc/api/fs.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7899,7 +7899,8 @@ StatFs {
78997899
bfree: 61058895,
79007900
bavail: 61058895,
79017901
files: 999,
7902-
ffree: 1000000
7902+
ffree: 1000000,
7903+
frsize: 4096
79037904
}
79047905
```
79057906
@@ -7913,7 +7914,8 @@ StatFs {
79137914
bfree: 61058895n,
79147915
bavail: 61058895n,
79157916
files: 999n,
7916-
ffree: 1000000n
7917+
ffree: 1000000n,
7918+
frsize: 4096n
79177919
}
79187920
```
79197921
@@ -7989,6 +7991,20 @@ added:
79897991
79907992
Total file nodes in file system.
79917993
7994+
#### `statfs.frsize`
7995+
7996+
<!-- YAML
7997+
added: REPLACEME
7998+
-->
7999+
8000+
* Type: {number|bigint}
8001+
8002+
Fundamental file system block size. This is the unit in which `blocks`,
8003+
`bfree`, and `bavail` are counted. On most file systems this equals `bsize`,
8004+
but on FUSE mounts (e.g. Docker Desktop on macOS using VirtioFS) they can
8005+
differ. Use `frsize` (not `bsize`) when calculating disk space from block
8006+
counts.
8007+
79928008
#### `statfs.type`
79938009
79948010
<!-- YAML

lib/internal/fs/utils.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,20 +571,22 @@ function getStatsFromBinding(stats, offset = 0) {
571571
}
572572

573573
class StatFs {
574-
constructor(type, bsize, blocks, bfree, bavail, files, ffree) {
574+
constructor(type, bsize, blocks, bfree, bavail, files, ffree, frsize) {
575575
this.type = type;
576576
this.bsize = bsize;
577577
this.blocks = blocks;
578578
this.bfree = bfree;
579579
this.bavail = bavail;
580580
this.files = files;
581581
this.ffree = ffree;
582+
this.frsize = frsize;
582583
}
583584
}
584585

585586
function getStatFsFromBinding(stats) {
586587
return new StatFs(
587588
stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], stats[6],
589+
stats[7],
588590
);
589591
}
590592

src/node_file-inl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ void FillStatFsArray(AliasedBufferBase<NativeT, V8T>* fields,
158158
SET_FIELD(kBAvail, s->f_bavail);
159159
SET_FIELD(kFiles, s->f_files);
160160
SET_FIELD(kFFree, s->f_ffree);
161+
SET_FIELD(kFrSize, s->f_frsize);
161162

162163
#undef SET_FIELD
163164
}

src/node_file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum class FsStatFsOffset {
4949
kBAvail,
5050
kFiles,
5151
kFFree,
52+
kFrSize,
5253
kFsStatFsFieldsNumber
5354
};
5455

test/parallel/test-fs-promises.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ function verifyStatFsObject(stat, isBigint = false) {
9494
assert.strictEqual(typeof stat.bavail, valueType);
9595
assert.strictEqual(typeof stat.files, valueType);
9696
assert.strictEqual(typeof stat.ffree, valueType);
97+
assert.strictEqual(typeof stat.frsize, valueType);
9798
}
9899

99100
async function getHandle(dest) {

test/parallel/test-fs-statfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function verifyStatFsObject(statfs, isBigint = false) {
77
const valueType = isBigint ? 'bigint' : 'number';
88

99
[
10-
'type', 'bsize', 'blocks', 'bfree', 'bavail', 'files', 'ffree',
10+
'type', 'bsize', 'blocks', 'bfree', 'bavail', 'files', 'ffree', 'frsize',
1111
].forEach((k) => {
1212
assert.ok(Object.hasOwn(statfs, k));
1313
assert.strictEqual(typeof statfs[k], valueType,

0 commit comments

Comments
 (0)