mrf: Avoid rare data race and more simplification (#12791)

This change avoids a rare data race and simplify the function that
returns MRF last activity information.
This commit is contained in:
Anis Elleuch 2021-07-26 16:00:59 +01:00 committed by GitHub
parent 7106e9394c
commit 39874b77ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 44 deletions

View File

@ -68,17 +68,6 @@ func newBgHealSequence() *healSequence {
} }
} }
func getCurrentMRFStatus() madmin.MRFStatus {
mrfInfo := globalMRFState.getCurrentMRFRoundInfo()
return madmin.MRFStatus{
BytesHealed: mrfInfo.bytesHealed,
ItemsHealed: mrfInfo.itemsHealed,
TotalItems: mrfInfo.itemsHealed + mrfInfo.pendingItems,
TotalBytes: mrfInfo.bytesHealed + mrfInfo.pendingBytes,
Started: mrfInfo.triggeredAt,
}
}
// getBackgroundHealStatus will return the // getBackgroundHealStatus will return the
func getBackgroundHealStatus(ctx context.Context, o ObjectLayer) (madmin.BgHealState, bool) { func getBackgroundHealStatus(ctx context.Context, o ObjectLayer) (madmin.BgHealState, bool) {
if globalBackgroundHealState == nil { if globalBackgroundHealState == nil {
@ -94,9 +83,9 @@ func getBackgroundHealStatus(ctx context.Context, o ObjectLayer) (madmin.BgHealS
ScannedItemsCount: bgSeq.getScannedItemsCount(), ScannedItemsCount: bgSeq.getScannedItemsCount(),
} }
if globalMRFState != nil { if globalMRFState.initialized() {
status.MRF = map[string]madmin.MRFStatus{ status.MRF = map[string]madmin.MRFStatus{
globalLocalNodeName: getCurrentMRFStatus(), globalLocalNodeName: globalMRFState.getCurrentMRFRoundInfo(),
} }
} }

View File

@ -293,7 +293,7 @@ var (
globalBackgroundHealRoutine *healRoutine globalBackgroundHealRoutine *healRoutine
globalBackgroundHealState *allHealState globalBackgroundHealState *allHealState
globalMRFState *mrfState globalMRFState mrfState
// If writes to FS backend should be O_SYNC. // If writes to FS backend should be O_SYNC.
globalFSOSync bool globalFSOSync bool

View File

@ -20,6 +20,7 @@ package cmd
import ( import (
"context" "context"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/minio/madmin-go" "github.com/minio/madmin-go"
@ -48,19 +49,11 @@ type setInfo struct {
index, pool int index, pool int
} }
type mrfStats struct {
triggeredAt time.Time
itemsHealed uint64
bytesHealed uint64
pendingItems uint64
pendingBytes uint64
}
// mrfState sncapsulates all the information // mrfState sncapsulates all the information
// related to the global background MRF. // related to the global background MRF.
type mrfState struct { type mrfState struct {
ready int32
ctx context.Context ctx context.Context
objectAPI ObjectLayer objectAPI ObjectLayer
@ -77,9 +70,30 @@ type mrfState struct {
triggeredAt time.Time triggeredAt time.Time
} }
// Initialize healing MRF subsystem
func (m *mrfState) init(ctx context.Context, objAPI ObjectLayer) {
m.mu.Lock()
defer m.mu.Unlock()
m.ctx = ctx
m.objectAPI = objAPI
m.opCh = make(chan partialOperation, mrfOpsQueueSize)
m.pendingOps = make(map[partialOperation]setInfo)
m.setReconnectEvent = make(chan setInfo)
go globalMRFState.maintainMRFList()
go globalMRFState.healRoutine()
atomic.StoreInt32(&m.ready, 1)
}
func (m *mrfState) initialized() bool {
return atomic.LoadInt32(&m.ready) != 0
}
// Add a partial S3 operation (put/delete) when one or more disks are offline. // Add a partial S3 operation (put/delete) when one or more disks are offline.
func (m *mrfState) addPartialOp(op partialOperation) { func (m *mrfState) addPartialOp(op partialOperation) {
if m == nil { if !m.initialized() {
return return
} }
@ -91,7 +105,7 @@ func (m *mrfState) addPartialOp(op partialOperation) {
// Receive the new set (disk) reconnection event // Receive the new set (disk) reconnection event
func (m *mrfState) newSetReconnected(pool, set int) { func (m *mrfState) newSetReconnected(pool, set int) {
if m == nil { if !m.initialized() {
return return
} }
@ -104,8 +118,8 @@ func (m *mrfState) newSetReconnected(pool, set int) {
} }
} }
// Get current MRF stats // Get current MRF stats of the last MRF activity
func (m *mrfState) getCurrentMRFRoundInfo() mrfStats { func (m *mrfState) getCurrentMRFRoundInfo() madmin.MRFStatus {
m.mu.Lock() m.mu.Lock()
triggeredAt := m.triggeredAt triggeredAt := m.triggeredAt
itemsHealed := m.itemsHealed itemsHealed := m.itemsHealed
@ -115,15 +129,15 @@ func (m *mrfState) getCurrentMRFRoundInfo() mrfStats {
m.mu.Unlock() m.mu.Unlock()
if pendingItems == 0 { if pendingItems == 0 {
return mrfStats{} return madmin.MRFStatus{}
} }
return mrfStats{ return madmin.MRFStatus{
triggeredAt: triggeredAt, Started: triggeredAt,
itemsHealed: itemsHealed, ItemsHealed: itemsHealed,
bytesHealed: bytesHealed, BytesHealed: bytesHealed,
pendingItems: pendingItems, TotalItems: itemsHealed + pendingItems,
pendingBytes: pendingBytes, TotalBytes: bytesHealed + pendingBytes,
} }
} }
@ -230,13 +244,5 @@ func (m *mrfState) healRoutine() {
// Initialize healing MRF // Initialize healing MRF
func initHealMRF(ctx context.Context, obj ObjectLayer) { func initHealMRF(ctx context.Context, obj ObjectLayer) {
globalMRFState = &mrfState{ globalMRFState.init(ctx, obj)
ctx: ctx,
objectAPI: obj,
opCh: make(chan partialOperation, mrfOpsQueueSize),
pendingOps: make(map[partialOperation]setInfo),
setReconnectEvent: make(chan setInfo),
}
go globalMRFState.maintainMRFList()
go globalMRFState.healRoutine()
} }