Debugging "directory not empty" errors from os.RemoveAll on a custom FUSE filesystem
This article details the investigation of a "directory not empty" failure when using Go's os.RemoveAll on a self‑built FUSE‑based distributed filesystem, describing the kernel readdir offset issue, the debugging steps taken, and the final fix applied.
Background : A Go program compiled for a custom distributed filesystem mounted via FUSE failed when calling os.RemoveAll(dir) on a non‑empty directory, reporting "directory not empty".
Investigation Process : The team examined the FUSE client implementation, noting that FUSE operates as a user‑space filesystem framework. They reproduced the issue by creating a directory with 300 files and running the removal script, which consistently triggered the error.
Root Cause : The kernel, during a readdir operation, received an interrupt signal and resent the request from the previous offset to /dev/fuse. The client incorrectly discarded the partially returned data, causing subsequent reads to fail because the expected offset data was missing. This manifested as incomplete unlink operations and the "directory not empty" error.
Detailed Trace : The kernel invokes sys_getdents64, which leads to iterate_dir in VFS, then to fuse_readdir. The response is copied to user space via dir_emit. At a certain point, signal_pending(current) returned -4, interrupting processing and forcing a retry from the original offset, exposing the bug.
Fix : After confirming the signal handling was normal, the team corrected the distributed filesystem logic to properly handle interrupted readdir calls and ensure all files are unlinked before removing the directory. The issue was resolved.
Kernel Module Build Commands :
make CONFIG_FUSE_FS=m M=fs/fuse</code>
<code>yes | cp fs/fuse/fuse.ko /usr/lib/modules/4.18.0_80.7.1.el8_0_bch_v1.0/kernel/fs/fuse/</code>
<code>umount /mnt</code>
<code>umount /sys/fs/fuse/connections/</code>
<code>rmmod fuse</code>
<code>insmod /usr/lib/modules/4.18.0_80.7.1.el8_0_bch_v1.0/kernel/fs/fuse/fuse.koFtrace Debugging Commands :
cd /sys/kernel/debug/tracing</code>
<code>echo 0 > tracing_on</code>
<code>echo > trace</code>
<code>echo syscalls:* > set_event</code>
<code>echo raw_syscalls:* >> set_event</code>
<code>echo ${pid} >> set_event_pid</code>
<code>echo 1 > tracing_on</code>
<code># run the program</code>
<code>cat traceThe experience shared aims to help others encountering similar FUSE‑related filesystem issues.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
360 Smart Cloud
Official service account of 360 Smart Cloud, dedicated to building a high-quality, secure, highly available, convenient, and stable one‑stop cloud service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
