Skip to content

Commit cf47d28

Browse files
committed
lib/std/posix/test.zig: don't compare blksize in "fstatat"
In trying to reproduce the race in #24380, my system tripped over the stat "blocks" field changing in this test. The value was almost always 8 (effectively 4k) or very infrequently 0 (I saw the 0 from both `fstat` and `fstatat`). I believe the underlying filesystem is free to asynchronously change this value. For example, if it migrates a file between some "inline" or maybe journal storage, and actual on-disk blocks. So it seems plausible that its allowed to change between stat calls. Breaking up the struct comparison this way means we also don't compare any of the padding or "reserved" fields, too. And we can narrow down the s390x-linux work-around.
1 parent caf80e9 commit cf47d28

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

lib/std/posix/test.zig

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,27 @@ test "fstatat" {
395395
// now repeat but using `fstatat` instead
396396
const statat = try posix.fstatat(tmp.dir.fd, "file.txt", posix.AT.SYMLINK_NOFOLLOW);
397397

398-
// s390x-linux does not have nanosecond precision for fstat(), but it does for fstatat(). As a
399-
// result, comparing the two structures is doomed to fail.
400-
if (builtin.cpu.arch == .s390x and builtin.os.tag == .linux) return error.SkipZigTest;
401-
402-
try expectEqual(stat, statat);
398+
try expectEqual(stat.dev, statat.dev);
399+
try expectEqual(stat.ino, statat.ino);
400+
try expectEqual(stat.nlink, statat.nlink);
401+
try expectEqual(stat.mode, statat.mode);
402+
try expectEqual(stat.uid, statat.uid);
403+
try expectEqual(stat.gid, statat.gid);
404+
try expectEqual(stat.rdev, statat.rdev);
405+
try expectEqual(stat.size, statat.size);
406+
try expectEqual(stat.blksize, statat.blksize);
407+
408+
// The stat.blocks/statat.blocks count is managed by the filesystem and may
409+
// change if the file is stored in a journal or "inline".
410+
// try expectEqual(stat.blocks, statat.blocks);
411+
412+
// s390x-linux does not have nanosecond precision for fstat(), but it does for
413+
// fstatat(). As a result, comparing the timestamps isn't worth the effort
414+
if (!(builtin.cpu.arch == .s390x and builtin.os.tag == .linux)) {
415+
try expectEqual(stat.atime(), statat.atime());
416+
try expectEqual(stat.mtime(), statat.mtime());
417+
try expectEqual(stat.ctime(), statat.ctime());
418+
}
403419
}
404420

405421
test "readlinkat" {

0 commit comments

Comments
 (0)