@@ -7,7 +7,10 @@ import (
77 "errors"
88 "fmt"
99 "net"
10+ "os"
11+ "path/filepath"
1012 "regexp"
13+ "strings"
1114 "sync"
1215
1316 "github.com/go-git/go-billy/v5"
@@ -101,6 +104,8 @@ func (h *NFSHandler) OnNetworkRelease(ctx context.Context, sbx *sandbox.Sandbox)
101104 h .mu .Unlock ()
102105
103106 for _ , chroot := range chroots {
107+ h .removeNFSOrphans (ctx , sbx .Runtime .SandboxID , chroot .Root ())
108+
104109 err := chroot .Close ()
105110 if err != nil {
106111 logger .L ().Warn (ctx , "failed to close chroot" ,
@@ -114,6 +119,46 @@ func (h *NFSHandler) OnNetworkRelease(ctx context.Context, sbx *sandbox.Sandbox)
114119 }
115120}
116121
122+ // removeNFSOrphans removes .nfs* files left by the NFS silly-rename mechanism.
123+ // When an NFS client deletes a file that still has open fds, it renames the file
124+ // to .nfsXXXX instead of removing it, and sends a REMOVE only after the last fd
125+ // is closed. If the client VM is killed before closing its fds, the .nfs* file
126+ // remains on the server permanently. This function cleans them up at sandbox teardown.
127+ func (h * NFSHandler ) removeNFSOrphans (ctx context.Context , sandboxID , dir string ) {
128+ entries , err := os .ReadDir (dir )
129+ if err != nil {
130+ if ! os .IsNotExist (err ) {
131+ logger .L ().Warn (ctx , "failed to read volume dir for NFS orphan cleanup" ,
132+ logger .WithSandboxID (sandboxID ),
133+ zap .String ("dir" , dir ),
134+ zap .Error (err ),
135+ )
136+ }
137+
138+ return
139+ }
140+
141+ for _ , entry := range entries {
142+ if ! strings .HasPrefix (entry .Name (), ".nfs" ) {
143+ continue
144+ }
145+
146+ path := filepath .Join (dir , entry .Name ())
147+ if err := os .Remove (path ); err != nil && ! os .IsNotExist (err ) {
148+ logger .L ().Warn (ctx , "failed to remove NFS orphan file" ,
149+ logger .WithSandboxID (sandboxID ),
150+ zap .String ("path" , path ),
151+ zap .Error (err ),
152+ )
153+ } else {
154+ logger .L ().Info (ctx , "removed NFS orphan file" ,
155+ logger .WithSandboxID (sandboxID ),
156+ zap .String ("path" , path ),
157+ )
158+ }
159+ }
160+ }
161+
117162func (h * NFSHandler ) Mount (
118163 ctx context.Context ,
119164 conn net.Conn ,
0 commit comments