From 2540141ee71ce6aac1411f7cba2074ff76c61e2b Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Thu, 2 Jul 2026 13:39:21 -0700 Subject: [PATCH] fix(fuse-tests): don't declare the FUSE mount ready before it is mounted (#10208) waitForMount probed the mount point with stat+ReadDir, which a bare local directory also passes, so Setup could return before the weed mount process finished mounting. Tests then wrote to the local disk underneath the mount point; when the mount activated it shadowed those files, producing the intermittent TestConcurrentFileOperations/ConcurrentReadWrite ENOENT with an empty ReadDir. Require the mount point's device ID to differ from its parent's before reporting ready. --- test/fuse_integration/framework_test.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/test/fuse_integration/framework_test.go b/test/fuse_integration/framework_test.go index 91497aad3..83aa1e75c 100644 --- a/test/fuse_integration/framework_test.go +++ b/test/fuse_integration/framework_test.go @@ -333,11 +333,19 @@ func (f *FuseTestFramework) waitForService(addr string, timeout time.Duration) e return fmt.Errorf("service at %s not ready within timeout", addr) } -// waitForMount waits for the FUSE mount to be ready +// waitForMount waits for the FUSE mount to be ready. A stat/ReadDir probe +// alone is not enough: the bare mount point directory passes both before the +// mount process finishes starting, letting tests race ahead and write to the +// local disk underneath the mount. The mount point's device ID differing from +// its parent's confirms a filesystem is actually mounted there. func (f *FuseTestFramework) waitForMount(timeout time.Duration) error { + parentDev, err := deviceID(filepath.Dir(f.mountPoint)) + if err != nil { + return fmt.Errorf("stat mount point parent: %v", err) + } deadline := time.Now().Add(timeout) for time.Now().Before(deadline) { - if _, err := os.Stat(f.mountPoint); err == nil { + if dev, err := deviceID(f.mountPoint); err == nil && dev != parentDev { if _, err := os.ReadDir(f.mountPoint); err == nil { return nil } @@ -347,6 +355,15 @@ func (f *FuseTestFramework) waitForMount(timeout time.Duration) error { return fmt.Errorf("mount point not ready within timeout") } +// deviceID returns the device ID of the filesystem containing path. +func deviceID(path string) (uint64, error) { + var st syscall.Stat_t + if err := syscall.Stat(path, &st); err != nil { + return 0, err + } + return uint64(st.Dev), nil +} + // findWeedBinary locates the weed binary. func findWeedBinary() string { if p, err := exec.LookPath("weed"); err == nil {