From 1d0fde434fac309d32a490eeea9d03507d23cad9 Mon Sep 17 00:00:00 2001 From: Sherman Beus Date: Fri, 29 Mar 2024 11:51:45 -0700 Subject: [PATCH] Removes previous addition of an "io lock" due to the potential for a deadlock (actually happened) and no straight-forward work around. Worst case scenario is that the pruneTree function removes a directory just as another bit of logic was going to write to it and there's an error. STS is pretty fault tolerant, so the request would just be tried again anyway. Seems fine without that additional locking. --- stage/local.go | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/stage/local.go b/stage/local.go index e21bdd3..4edba30 100644 --- a/stage/local.go +++ b/stage/local.go @@ -102,12 +102,6 @@ type Stage struct { cacheTime time.Time cacheTimes []time.Time - // Every normal file I/O function does a read lock, so write locking - // it will block the stage area from interacting with the file system. - // This is useful for when we want to clean up the stage and target - // areas. - ioLock sync.RWMutex - pathLock sync.RWMutex pathLocks map[string]*sync.RWMutex readyLock sync.RWMutex @@ -181,8 +175,6 @@ func (s *Stage) pathToName(path, stripExt string) (name string) { // Scan walks the stage area tree looking for companion files and returns any // found in the form of a JSON-encoded byte array func (s *Stage) Scan(version string) (jsonBytes []byte, err error) { - s.ioLock.RLock() - defer s.ioLock.RUnlock() var name string var lock *sync.RWMutex var partials []*sts.Partial @@ -216,8 +208,6 @@ func (s *Stage) Scan(version string) (jsonBytes []byte, err error) { } func (s *Stage) initStageFile(path string, size int64) error { - s.ioLock.RLock() - defer s.ioLock.RUnlock() var err error info, err := os.Stat(path + partExt) if err == nil && info.Size() == size { @@ -266,9 +256,6 @@ func (s *Stage) Prepare(parts []sts.Binned) { // Receive reads a single file part with file metadata and reader func (s *Stage) Receive(file *sts.Partial, reader io.Reader) (err error) { - s.ioLock.RLock() - defer s.ioLock.RUnlock() - if len(file.Parts) != 1 { err = fmt.Errorf( "can only receive a single part for a single reader (%d given)", @@ -460,8 +447,6 @@ func (s *Stage) setCanReceive(value bool) { // files in the stage area that should be completed from the previous server // run func (s *Stage) Recover() { - s.ioLock.Lock() - defer s.ioLock.Unlock() s.setCanReceive(false) defer s.setCanReceive(true) s.logInfo("Beginning stage recovery") @@ -602,9 +587,8 @@ func (s *Stage) scheduleClean(minAge time.Duration) { } func (s *Stage) pruneTree(dir string, minAge time.Duration) { - s.ioLock.Lock() - defer s.ioLock.Unlock() - s.logDebug("Pruning empty directories ...") + s.logInfo("Pruning empty directories ...") + defer s.logInfo("Pruning complete") var dirs []string err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { @@ -798,8 +782,6 @@ func (s *Stage) processHandler() { } func (s *Stage) process(file *finalFile) { - s.ioLock.RLock() - defer s.ioLock.RUnlock() s.logDebug("Validating:", file.name) @@ -978,8 +960,6 @@ func (s *Stage) finalize(file *finalFile) { } func (s *Stage) putFileAway(file *finalFile) (targetPath string, err error) { - s.ioLock.RLock() - defer s.ioLock.RUnlock() // Better to log the file twice rather than receive it twice. If we log // after putting the file away, it's possible that a crash could occur