frostfs-node/pkg/local_object_storage/blobstor
Alex Vanin e6f2d84736 [#246] blobovnivza: Fix deadlock on concurrent evict and open new blobovnicza
Deadlock occurs when `getActivate` function opens new blobovnicza and that
invokes evict in LRU cache of open blobovniczas. `getActivate` makes
`activeMtx.Lock()` and then cache evict makes `activeMtx.RLock()` and deadlock
happens.

Fix contains two steps:
- add separate mutex to open blobovniczas (1),
- split single Lock outside of `updateAndGet` (2).

As for the (1) `bbolt.Open()` locks when it tries to open the same file from
two threads. So separate mutex will prevent that.

As for the (2) `updateAndGet` function contains from two parts. At first it
checks if required blobovnicza is ready and it returns it. In this case we can
use the simple RLock. But then there is an option when we should open new
blobovnicza and update map of active blobovniczas.

In this case we call `openBlobovnicza` without activeMtx lock. Cache evict
happens there and it won't cause deadlock.

Then we lock activeMtx to update the map of active blobovniczas. Concurrency can
happen there. However `openBlobovnicza` will not open the same blobovnicza twice,
so we can make one more check if opened blobovnicza was activated while thread was
locked in activeMtx. If so, then return active blobovnicza, else finish activation.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2020-12-14 13:37:45 +03:00
..
blobovnicza.go [#246] blobovnivza: Fix deadlock on concurrent evict and open new blobovnicza 2020-12-14 13:37:45 +03:00
blobovnicza_test.go [#222] Rename WithTreeRoot.. to WithRoot.. in blobstor opts 2020-12-11 17:19:37 +03:00
blobstor.go [#222] Rename WithTreeRoot.. to WithRoot.. in blobstor opts 2020-12-11 17:19:37 +03:00
compress.go [#176] blobstor: Handle error of zstd (de)compressor creation 2020-12-11 17:19:37 +03:00
control.go [#220] blobstor: Add blobovnicza tree structure to BlobStor 2020-12-11 17:19:37 +03:00
delete_big.go [#220] localstorage: Replace basic errors to core library 2020-12-11 17:19:37 +03:00
delete_small.go [#220] blobstor: Implement "small" operations 2020-12-11 17:19:37 +03:00
exists.go [#211] blobstor: Implement Exists method 2020-12-11 17:19:37 +03:00
fstree.go [#189] blobstor: Implement DumpInfo method 2020-12-11 17:19:37 +03:00
get_big.go [#220] localstorage: Replace basic errors to core library 2020-12-11 17:19:37 +03:00
get_range_big.go [#235] blobstor: Return object.ErrRangeOutOfBounds from shallow dir 2020-12-11 17:19:37 +03:00
get_range_small.go [#235] blobstor: Return object.ErrRangeOutOfBounds from shallow dir 2020-12-11 17:19:37 +03:00
get_small.go [#220] blobstor: Implement "small" operations 2020-12-11 17:19:37 +03:00
info.go [#189] blobstor: Implement DumpInfo method 2020-12-11 17:19:37 +03:00
iterate.go [#211] blobstor: Define Iterate operation 2020-12-11 17:19:37 +03:00
put.go [#229] blobovnicza: Store objects in a binary format 2020-12-11 17:19:37 +03:00
util.go [#211] blobstor: Rename GetRange to GetRangeBig 2020-12-11 17:19:37 +03:00