[FIXED] JetStream: possible lock inversion

When updating usage, there is a lock inversion in that the jetStream
lock was acquired while under the stream's (mset) lock, which is
not correct. Also, updateUsage was locking the jsAccount lock, which
again, is not really correct since jsAccount contains streams, so
it should be jsAccount->stream, not the other way around.

Removed the locking of jetStream to check for clustered state since
js.clustered is immutable.

Replaced using jsAccount lock to update usage with a dedicated lock.

Originally moved all the update/limit fields in jsAccount to new
structure to make sure that I would see all code that is updating
or reading those fields, and also all functions so that I could
make sure that I use the new lock when calling these. Once that
works was done, and to reduce code changes, I put the fields back
into jsAccount (although I grouped them under the new usageMu mutex
field).

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
Ivan Kozlovic
2022-05-02 09:50:32 -06:00
parent ea6a43ead9
commit 5050092468
6 changed files with 77 additions and 63 deletions

View File

@@ -2576,6 +2576,7 @@ func (s *Server) accountDetail(jsa *jsAccount, optStreams, optConsumers, optCfg
if acc.nameTag != "" {
name = acc.nameTag
}
jsa.usageMu.RLock()
totalMem, totalStore := jsa.storageTotals()
detail := AccountDetail{
Name: name,
@@ -2590,6 +2591,7 @@ func (s *Server) accountDetail(jsa *jsAccount, optStreams, optConsumers, optCfg
},
Streams: make([]StreamDetail, 0, len(jsa.streams)),
}
jsa.usageMu.RUnlock()
var streams []*stream
if optStreams {
for _, stream := range jsa.streams {