From: Tom Clegg Date: Wed, 11 Dec 2019 15:40:01 +0000 (-0500) Subject: 15928: Fix deadlock. X-Git-Tag: 1.4.3~6 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/947370baeacd86738446bb2ea6a209390e0d83dc 15928: Fix deadlock. Locking the parent dir isn't necessary to finish async writes, and deadlocks if a waitPrune() is waiting for the async writes to finish. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- diff --git a/sdk/go/arvados/fs_collection.go b/sdk/go/arvados/fs_collection.go index d206cb3b24..609eeb6e9e 100644 --- a/sdk/go/arvados/fs_collection.go +++ b/sdk/go/arvados/fs_collection.go @@ -695,21 +695,9 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize go func() { defer close(done) defer close(errs) - locked := map[*filenode]bool{} locator, _, err := dn.fs.PutB(block) dn.fs.throttle().Release() { - if !sync { - dn.Lock() - defer dn.Unlock() - for _, name := range dn.sortedNames() { - if fn, ok := dn.inodes[name].(*filenode); ok { - fn.Lock() - defer fn.Unlock() - locked[fn] = true - } - } - } defer func() { for _, seg := range segs { if seg.flushing == done { @@ -724,6 +712,7 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize } for idx, ref := range refs { if !sync { + ref.fn.Lock() // In async mode, fn's lock was // released while we were waiting for // PutB(); lots of things might have @@ -732,17 +721,15 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize // file segments have // rearranged or changed in // some way + ref.fn.Unlock() continue } else if seg, ok := ref.fn.segments[ref.idx].(*memSegment); !ok || seg != segs[idx] { // segment has been replaced + ref.fn.Unlock() continue } else if seg.flushing != done { // seg.buf has been replaced - continue - } else if !locked[ref.fn] { - // file was renamed, moved, or - // deleted since we called - // PutB + ref.fn.Unlock() continue } } @@ -760,6 +747,9 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize // lock, writing different segments from the // same file. atomic.AddInt64(&ref.fn.memsize, -int64(len(data))) + if !sync { + ref.fn.Unlock() + } } }() if sync {