mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Hold locks granularly in nslockMap (#6242)
With benchmarks increases the performance for small files by almost 4x times the previous releases.
This commit is contained in:
parent
eabfcea34e
commit
13fbb96736
@ -133,31 +133,31 @@ type nsLockMap struct {
|
|||||||
// Indicates if namespace is part of a distributed setup.
|
// Indicates if namespace is part of a distributed setup.
|
||||||
isDistXL bool
|
isDistXL bool
|
||||||
lockMap map[nsParam]*nsLock
|
lockMap map[nsParam]*nsLock
|
||||||
lockMapMutex sync.Mutex
|
lockMapMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock the namespace resource.
|
// Lock the namespace resource.
|
||||||
func (n *nsLockMap) lock(volume, path string, lockSource, opsID string, readLock bool, timeout time.Duration) (locked bool) {
|
func (n *nsLockMap) lock(volume, path string, lockSource, opsID string, readLock bool, timeout time.Duration) (locked bool) {
|
||||||
var nsLk *nsLock
|
var nsLk *nsLock
|
||||||
n.lockMapMutex.Lock()
|
|
||||||
|
|
||||||
|
n.lockMapMutex.Lock()
|
||||||
param := nsParam{volume, path}
|
param := nsParam{volume, path}
|
||||||
nsLk, found := n.lockMap[param]
|
nsLk, found := n.lockMap[param]
|
||||||
if !found {
|
if !found {
|
||||||
nsLk = &nsLock{
|
n.lockMap[param] = &nsLock{
|
||||||
RWLockerSync: func() RWLockerSync {
|
RWLockerSync: func() RWLockerSync {
|
||||||
if n.isDistXL {
|
if n.isDistXL {
|
||||||
return dsync.NewDRWMutex(pathJoin(volume, path), globalDsync)
|
return dsync.NewDRWMutex(pathJoin(volume, path), globalDsync)
|
||||||
}
|
}
|
||||||
return &lsync.LRWMutex{}
|
return &lsync.LRWMutex{}
|
||||||
}(),
|
}(),
|
||||||
ref: 0,
|
ref: 1,
|
||||||
}
|
}
|
||||||
n.lockMap[param] = nsLk
|
nsLk = n.lockMap[param]
|
||||||
|
} else {
|
||||||
|
// Update ref count here to avoid multiple races.
|
||||||
|
nsLk.ref++
|
||||||
}
|
}
|
||||||
nsLk.ref++ // Update ref count here to avoid multiple races.
|
|
||||||
|
|
||||||
// Unlock map before Locking NS which might block.
|
|
||||||
n.lockMapMutex.Unlock()
|
n.lockMapMutex.Unlock()
|
||||||
|
|
||||||
// Locking here will block (until timeout).
|
// Locking here will block (until timeout).
|
||||||
@ -168,44 +168,44 @@ func (n *nsLockMap) lock(volume, path string, lockSource, opsID string, readLock
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !locked { // We failed to get the lock
|
if !locked { // We failed to get the lock
|
||||||
|
|
||||||
|
// Decrement ref count since we failed to get the lock
|
||||||
n.lockMapMutex.Lock()
|
n.lockMapMutex.Lock()
|
||||||
defer n.lockMapMutex.Unlock()
|
nsLk.ref--
|
||||||
|
|
||||||
nsLk.ref-- // Decrement ref count since we failed to get the lock
|
|
||||||
|
|
||||||
if nsLk.ref == 0 {
|
if nsLk.ref == 0 {
|
||||||
// Remove from the map if there are no more references.
|
// Remove from the map if there are no more references.
|
||||||
delete(n.lockMap, param)
|
delete(n.lockMap, param)
|
||||||
}
|
}
|
||||||
|
n.lockMapMutex.Unlock()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock the namespace resource.
|
// Unlock the namespace resource.
|
||||||
func (n *nsLockMap) unlock(volume, path, opsID string, readLock bool) {
|
func (n *nsLockMap) unlock(volume, path, opsID string, readLock bool) {
|
||||||
// nsLk.Unlock() will not block, hence locking the map for the
|
|
||||||
// entire function is fine.
|
|
||||||
n.lockMapMutex.Lock()
|
|
||||||
defer n.lockMapMutex.Unlock()
|
|
||||||
|
|
||||||
param := nsParam{volume, path}
|
param := nsParam{volume, path}
|
||||||
if nsLk, found := n.lockMap[param]; found {
|
n.lockMapMutex.RLock()
|
||||||
|
nsLk, found := n.lockMap[param]
|
||||||
|
n.lockMapMutex.RUnlock()
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
if readLock {
|
if readLock {
|
||||||
nsLk.RUnlock()
|
nsLk.RUnlock()
|
||||||
} else {
|
} else {
|
||||||
nsLk.Unlock()
|
nsLk.Unlock()
|
||||||
}
|
}
|
||||||
|
n.lockMapMutex.Lock()
|
||||||
if nsLk.ref == 0 {
|
if nsLk.ref == 0 {
|
||||||
logger.LogIf(context.Background(), errors.New("Namespace reference count cannot be 0"))
|
logger.LogIf(context.Background(), errors.New("Namespace reference count cannot be 0"))
|
||||||
}
|
} else {
|
||||||
if nsLk.ref != 0 {
|
|
||||||
nsLk.ref--
|
nsLk.ref--
|
||||||
}
|
|
||||||
if nsLk.ref == 0 {
|
if nsLk.ref == 0 {
|
||||||
// Remove from the map if there are no more references.
|
// Remove from the map if there are no more references.
|
||||||
delete(n.lockMap, param)
|
delete(n.lockMap, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
n.lockMapMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock - locks the given resource for writes, using a previously
|
// Lock - locks the given resource for writes, using a previously
|
||||||
|
Loading…
Reference in New Issue
Block a user