From 7d0c9a6b3ddd90760027325a127d62f0242cfff7 Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 13 Mar 2025 10:20:40 +0100 Subject: [PATCH 1/5] Use the NODEFS filesystem in statfs when available --- src/lib/libfs.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lib/libfs.js b/src/lib/libfs.js index a5a505974fa61..b411be0db7dec 100644 --- a/src/lib/libfs.js +++ b/src/lib/libfs.js @@ -696,15 +696,30 @@ FS.staticInit(); return parent.node_ops.mknod(parent, name, mode, dev); }, statfs(path) { - return FS.statfsNode(FS.lookupPath(path, {follow: true}).node); + // When NODEFS is available, Emscripten still uses MEMFS as the default + // file system which doesn't have a statfs function. + // To ensure statfsNode has access to the statfs function, we pass in + // the NODEFS object. + if (this.filesystems.NODEFS) { + return FS.statfsNode({ + path, + node: this.filesystems.NODEFS, + }); + } + return FS.statfsNode({ + path, + node: FS.lookupPath(path, { + follow: true + }).node + }); }, statfsStream(stream) { // We keep a separate statfsStream function because noderawfs overrides // it. In noderawfs, stream.node is sometimes null. Instead, we need to // look at stream.path. - return FS.statfsNode(stream.node); + return FS.statfsNode(stream); }, - statfsNode(node) { + statfsNode({path, node}) { // NOTE: None of the defaults here are true. We're just returning safe and // sane values. Currently nodefs and rawfs replace these defaults, // other file systems leave them alone. @@ -718,11 +733,10 @@ FS.staticInit(); ffree: FS.nextInode - 1, fsid: 42, flags: 2, - namelen: 255, + namelen: 255 }; - if (node.node_ops.statfs) { - Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root)); + Object.assign(rtn, node.node_ops.statfs(path)); } return rtn; }, From cd33f4ee59ba558fe18c8ca0fed49da45b959240 Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 13 Mar 2025 11:48:32 +0100 Subject: [PATCH 2/5] Test number of block in statfs --- test/unistd/fstatfs.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/test/unistd/fstatfs.c b/test/unistd/fstatfs.c index be6c602d3e692..70d9c19a69d9b 100644 --- a/test/unistd/fstatfs.c +++ b/test/unistd/fstatfs.c @@ -8,14 +8,35 @@ int main() { struct statfs buf; int rtn; - assert(fstatfs(STDOUT_FILENO, &buf) == 0); + int fstatfs_rtn = fstatfs(STDOUT_FILENO, &buf); printf("f_type: %ld\n", buf.f_type); + assert(fstatfs_rtn == 0); + printf("f_blocks: %d\n", buf.f_blocks); + assert(buf.f_blocks == 1000000); int f = open("file", O_RDWR | O_CREAT); - assert(fstatfs(f, &buf) == 0); + fstatfs_rtn = fstatfs(f, &buf); printf("f_type: %ld\n", buf.f_type); + printf("f_blocks: %d\n", buf.f_blocks); +#if NODEFS + assert(fstatfs_rtn == 0); + assert(buf.f_blocks != 0); + // 2048000000 is a hardcoded value for NODEFS blocks. + assert(buf.f_blocks != 2048000000); +#else + assert(fstatfs_rtn == 0); + assert(buf.f_blocks == 1000000); +#endif assert(statfs("file", &buf) == 0); printf("f_type: %ld\n", buf.f_type); + printf("f_blocks: %d\n", buf.f_blocks); +#if NODEFS + assert(buf.f_blocks != 0); + assert(buf.f_blocks != 2048000000); +#else + assert(buf.f_blocks == 1000000); +#endif + return 0; } From b1b9b01bec4510ca593b880396b0755febeff547 Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 13 Mar 2025 12:59:41 +0100 Subject: [PATCH 3/5] Test NODERAWFS --- test/unistd/fstatfs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/unistd/fstatfs.c b/test/unistd/fstatfs.c index 70d9c19a69d9b..f58cfd142ef6d 100644 --- a/test/unistd/fstatfs.c +++ b/test/unistd/fstatfs.c @@ -18,11 +18,9 @@ int main() { fstatfs_rtn = fstatfs(f, &buf); printf("f_type: %ld\n", buf.f_type); printf("f_blocks: %d\n", buf.f_blocks); -#if NODEFS +#if NODEFS || NODERAWFS assert(fstatfs_rtn == 0); assert(buf.f_blocks != 0); - // 2048000000 is a hardcoded value for NODEFS blocks. - assert(buf.f_blocks != 2048000000); #else assert(fstatfs_rtn == 0); assert(buf.f_blocks == 1000000); @@ -31,9 +29,8 @@ int main() { assert(statfs("file", &buf) == 0); printf("f_type: %ld\n", buf.f_type); printf("f_blocks: %d\n", buf.f_blocks); -#if NODEFS +#if NODEFS || NODERAWFS assert(buf.f_blocks != 0); - assert(buf.f_blocks != 2048000000); #else assert(buf.f_blocks == 1000000); #endif From b53842ca0c462dcba197eb663ad2602541776d4d Mon Sep 17 00:00:00 2001 From: Bero Date: Wed, 19 Mar 2025 12:34:41 +0100 Subject: [PATCH 4/5] Test with real blocks count --- src/lib/libfs.js | 26 ++++++-------------------- test/setup_nodefs.js | 7 +++++++ test/unistd/fstatfs.c | 27 ++++++++++++++++++++++----- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/lib/libfs.js b/src/lib/libfs.js index b411be0db7dec..a5a505974fa61 100644 --- a/src/lib/libfs.js +++ b/src/lib/libfs.js @@ -696,30 +696,15 @@ FS.staticInit(); return parent.node_ops.mknod(parent, name, mode, dev); }, statfs(path) { - // When NODEFS is available, Emscripten still uses MEMFS as the default - // file system which doesn't have a statfs function. - // To ensure statfsNode has access to the statfs function, we pass in - // the NODEFS object. - if (this.filesystems.NODEFS) { - return FS.statfsNode({ - path, - node: this.filesystems.NODEFS, - }); - } - return FS.statfsNode({ - path, - node: FS.lookupPath(path, { - follow: true - }).node - }); + return FS.statfsNode(FS.lookupPath(path, {follow: true}).node); }, statfsStream(stream) { // We keep a separate statfsStream function because noderawfs overrides // it. In noderawfs, stream.node is sometimes null. Instead, we need to // look at stream.path. - return FS.statfsNode(stream); + return FS.statfsNode(stream.node); }, - statfsNode({path, node}) { + statfsNode(node) { // NOTE: None of the defaults here are true. We're just returning safe and // sane values. Currently nodefs and rawfs replace these defaults, // other file systems leave them alone. @@ -733,10 +718,11 @@ FS.staticInit(); ffree: FS.nextInode - 1, fsid: 42, flags: 2, - namelen: 255 + namelen: 255, }; + if (node.node_ops.statfs) { - Object.assign(rtn, node.node_ops.statfs(path)); + Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root)); } return rtn; }, diff --git a/test/setup_nodefs.js b/test/setup_nodefs.js index 5d1c38dd7898c..d51fb3befa181 100644 --- a/test/setup_nodefs.js +++ b/test/setup_nodefs.js @@ -1,3 +1,10 @@ +const statfsSync = require('fs').statfsSync; + +Module['preRun'] = () => { + const statfs = statfsSync('/'); + ENV.EXPECTED_BLOCKS = statfs.blocks.toString(); +}; + Module['onRuntimeInitialized'] = () => { out('mounting node filesystem under /nodefs'); FS.mkdir('/nodefs'); diff --git a/test/unistd/fstatfs.c b/test/unistd/fstatfs.c index f58cfd142ef6d..1bd567d79aabb 100644 --- a/test/unistd/fstatfs.c +++ b/test/unistd/fstatfs.c @@ -3,16 +3,33 @@ #include #include #include +#include +#include // for strerror +#include // for errno#include + +#define DEFAULT_BLOCKS 1000000 int main() { struct statfs buf; + const char *expected_blocks_str = getenv("EXPECTED_BLOCKS"); + long expected_blocks = expected_blocks_str ? atol(expected_blocks_str) : DEFAULT_BLOCKS; + + int fstatfs_rtn = statfs("/nodefs", &buf); + printf("f_type: %ld\n", buf.f_type); + assert(fstatfs_rtn == 0); + printf("f_blocks: %d\n", buf.f_blocks); + printf("expected_blocks: %ld\n", expected_blocks); +#if NODEFS || NODERAWFS + assert(buf.f_blocks == expected_blocks); +#else + assert(buf.f_blocks == DEFAULT_BLOCKS); +#endif - int rtn; - int fstatfs_rtn = fstatfs(STDOUT_FILENO, &buf); + fstatfs_rtn = fstatfs(STDOUT_FILENO, &buf); printf("f_type: %ld\n", buf.f_type); assert(fstatfs_rtn == 0); printf("f_blocks: %d\n", buf.f_blocks); - assert(buf.f_blocks == 1000000); + assert(buf.f_blocks == DEFAULT_BLOCKS); int f = open("file", O_RDWR | O_CREAT); fstatfs_rtn = fstatfs(f, &buf); @@ -23,7 +40,7 @@ int main() { assert(buf.f_blocks != 0); #else assert(fstatfs_rtn == 0); - assert(buf.f_blocks == 1000000); + assert(buf.f_blocks == DEFAULT_BLOCKS); #endif assert(statfs("file", &buf) == 0); @@ -32,7 +49,7 @@ int main() { #if NODEFS || NODERAWFS assert(buf.f_blocks != 0); #else - assert(buf.f_blocks == 1000000); + assert(buf.f_blocks == DEFAULT_BLOCKS); #endif return 0; From 5e8d3962a59e8719f12c4b163aafcd3ac7aedfea Mon Sep 17 00:00:00 2001 From: Bero Date: Wed, 19 Mar 2025 13:38:08 +0100 Subject: [PATCH 5/5] Limit real disk space test to only nodefs --- test/setup_nodefs.js | 10 ++++++++-- test/unistd/fstatfs.c | 7 +++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/setup_nodefs.js b/test/setup_nodefs.js index d51fb3befa181..03feef8cdd345 100644 --- a/test/setup_nodefs.js +++ b/test/setup_nodefs.js @@ -1,8 +1,14 @@ const statfsSync = require('fs').statfsSync; +const DEFAULT_BLOCKS = 1e6; + Module['preRun'] = () => { - const statfs = statfsSync('/'); - ENV.EXPECTED_BLOCKS = statfs.blocks.toString(); + try { + const statfs = statfsSync('/'); + ENV.EXPECTED_BLOCKS = statfs.blocks.toString(); + } catch (e) { + // Older versions of Node don't support statfsSync + } }; Module['onRuntimeInitialized'] = () => { diff --git a/test/unistd/fstatfs.c b/test/unistd/fstatfs.c index 1bd567d79aabb..e19b9e9b0a371 100644 --- a/test/unistd/fstatfs.c +++ b/test/unistd/fstatfs.c @@ -13,16 +13,15 @@ int main() { struct statfs buf; const char *expected_blocks_str = getenv("EXPECTED_BLOCKS"); long expected_blocks = expected_blocks_str ? atol(expected_blocks_str) : DEFAULT_BLOCKS; + int fstatfs_rtn; - int fstatfs_rtn = statfs("/nodefs", &buf); +#if NODEF || NODERAWFSS + fstatfs_rtn = statfs("/nodefs", &buf); printf("f_type: %ld\n", buf.f_type); assert(fstatfs_rtn == 0); printf("f_blocks: %d\n", buf.f_blocks); printf("expected_blocks: %ld\n", expected_blocks); -#if NODEFS || NODERAWFS assert(buf.f_blocks == expected_blocks); -#else - assert(buf.f_blocks == DEFAULT_BLOCKS); #endif fstatfs_rtn = fstatfs(STDOUT_FILENO, &buf);