Skip to content

Commit 866399a

Browse files
committed
Fix a possible race condition between rename & list due to the lack of locking around sealDir()
1 parent e8da120 commit 866399a

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

internal/dir.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,13 @@ func (parent *Inode) listObjectsSlurp(inode *Inode, startAfter string, sealEnd b
300300
for d, sealed := range dirs {
301301
// It's not safe to seal upper directories, we're not slurping at their start
302302
if (sealed || !resp.IsTruncated) && !d.isParentOf(inode) {
303+
if d != parent {
304+
d.mu.Lock()
305+
}
303306
d.sealDir()
307+
if d != parent {
308+
d.mu.Unlock()
309+
}
304310
}
305311
}
306312

@@ -321,7 +327,13 @@ func (parent *Inode) listObjectsSlurp(inode *Inode, startAfter string, sealEnd b
321327
}
322328

323329
if seal {
330+
if inode != parent {
331+
inode.mu.Lock()
332+
}
324333
inode.sealDir()
334+
if inode != parent {
335+
inode.mu.Unlock()
336+
}
325337
nextStartAfter = ""
326338
} else if obj != nil {
327339
// NextContinuationToken is not returned when delimiter is empty, so use obj.Key
@@ -388,6 +400,7 @@ func (dir *DirInodeData) checkGapLoaded(key string, newerThan time.Time) bool {
388400
return false
389401
}
390402

403+
// LOCKS_REQUIRED(inode.mu)
391404
func (inode *Inode) sealDir() {
392405
inode.dir.listMarker = nil
393406
inode.dir.listDone = true
@@ -401,7 +414,8 @@ func (inode *Inode) sealDir() {
401414
}
402415
}
403416

404-
// LOCKS_EXCLUDED(dh.inode.fs)
417+
// LOCKS_REQUIRED(dh.inode.mu)
418+
// LOCKS_EXCLUDED(dh.inode.fs.mu)
405419
func (dh *DirHandle) handleListResult(resp *ListBlobsOutput, prefix string, skipListing map[string]bool) {
406420
parent := dh.inode
407421
fs := parent.fs
@@ -506,7 +520,6 @@ func (dh *DirHandle) listObjectsFlat() (err error) {
506520

507521
dh.inode.mu.Lock()
508522
dh.handleListResult(resp, prefix, dh.inode.fs.completeInflightListing(myList))
509-
dh.inode.mu.Unlock()
510523

511524
if resp.IsTruncated && resp.NextContinuationToken != nil {
512525
// :-X idiotic aws-sdk with string pointers was leading to a huge memory leak here
@@ -539,6 +552,8 @@ func (dh *DirHandle) listObjectsFlat() (err error) {
539552
dh.inode.sealDir()
540553
}
541554

555+
dh.inode.mu.Unlock()
556+
542557
return
543558
}
544559

0 commit comments

Comments
 (0)