fix: refactor locks to apply them uniquely per node (#11052)

This refactor is done for few reasons below

- to avoid deadlocks in scenarios when number
  of nodes are smaller < actual erasure stripe
  count where in N participating local lockers
  can lead to deadlocks across systems.

- avoids expiry routines to run 1000 of separate
  network operations and routes per disk where
  as each of them are still accessing one single
  local entity.

- it is ideal to have since globalLockServer
  per instance.

- In a 32node deployment however, each server
  group is still concentrated towards the
  same set of lockers that partipicate during
  the write/read phase, unlike previous minio/dsync
  implementation - this potentially avoids send
  32 requests instead we will still send at max
  requests of unique nodes participating in a
  write/read phase.

- reduces overall chattiness on smaller setups.
This commit is contained in:
Harshavardhana
2020-12-10 07:28:37 -08:00
committed by GitHub
parent 97856bfebf
commit 4550ac6fff
17 changed files with 180 additions and 177 deletions

View File

@@ -130,21 +130,21 @@ func NewIDKey(time, memory uint32, threads uint8) func([]byte, []byte, []byte, [
pool := sync.Pool{
New: func() interface{} {
b := make([]block, memory)
return b
return &b
},
}
return func(password, salt, secret, data []byte, keyLen uint32) []byte {
B := pool.Get().([]block)
B := pool.Get().(*[]block)
defer func() {
clearBlocks(B)
clearBlocks(*B)
pool.Put(B)
}()
h0 := initHash(password, salt, secret, data, time, hashMemory, uint32(threads), keyLen, argon2id)
B = initBlocks(&h0, B, uint32(threads))
processBlocks(B, time, memory, uint32(threads), argon2id)
return extractKey(B, memory, uint32(threads), keyLen)
B1 := initBlocks(&h0, *B, uint32(threads))
processBlocks(B1, time, memory, uint32(threads), argon2id)
return extractKey(B1, memory, uint32(threads), keyLen)
}
}

View File

@@ -299,7 +299,9 @@ func lock(ctx context.Context, ds *Dsync, locks *[]string, id, source string, is
quorumLocked := checkQuorumLocked(locks, quorum) && locksFailed <= tolerance
if !quorumLocked {
log("Releasing all acquired locks now abandoned after quorum was not met\n")
releaseAll(ds, tolerance, owner, locks, isReadLock, restClnts, lockNames...)
if !releaseAll(ds, tolerance, owner, locks, isReadLock, restClnts, lockNames...) {
log("Unable to release acquired locks, stale locks might be present\n")
}
}
// We may have some unused results in ch, release them async.
@@ -308,11 +310,10 @@ func lock(ctx context.Context, ds *Dsync, locks *[]string, id, source string, is
close(ch)
for grantToBeReleased := range ch {
if grantToBeReleased.isLocked() {
// release lock
// release abandoned lock
log("Releasing abandoned lock\n")
sendRelease(ds, restClnts[grantToBeReleased.index],
owner,
grantToBeReleased.lockUID, isReadLock, lockNames...)
owner, grantToBeReleased.lockUID, isReadLock, lockNames...)
}
}
}()

View File

@@ -28,7 +28,11 @@ import (
"github.com/secure-io/sio-go/sioutil"
)
var idKey = argon2.NewIDKey(1, 64*1024, 4)
var idKey func([]byte, []byte, []byte, []byte, uint32) []byte
func init() {
idKey = argon2.NewIDKey(1, 64*1024, 4)
}
// EncryptData encrypts the data with an unique key
// derived from password using the Argon2id PBKDF.