From 82f1323af48512b4201b2ca973ac9063eb24b8bf Mon Sep 17 00:00:00 2001 From: Rakshith R Date: Mon, 9 Oct 2023 11:38:04 +0530 Subject: [PATCH] cephfs: safeguard localClusterState struct from race conditions Multiple go-routines may simultaneously check for a clusterID's presence in clusterAdditionalInfo and create an entry if it is absent. This set of operation needs to be serialized. Therefore, this commit safeguards clusterAdditionalInfo map from concurrent writes with a mutex to prevent the above problem. Signed-off-by: Rakshith R --- internal/cephfs/core/volume.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/internal/cephfs/core/volume.go b/internal/cephfs/core/volume.go index c95a7cc86..54c3dd4eb 100644 --- a/internal/cephfs/core/volume.go +++ b/internal/cephfs/core/volume.go @@ -22,6 +22,7 @@ import ( "fmt" "path" "strings" + "sync" cerrors "github.com/ceph/ceph-csi/internal/cephfs/errors" fsutil "github.com/ceph/ceph-csi/internal/cephfs/util" @@ -32,12 +33,17 @@ import ( "github.com/ceph/go-ceph/rados" ) -// clusterAdditionalInfo contains information regarding if resize is -// supported in the particular cluster and subvolumegroup is -// created or not. -// Subvolumegroup creation and volume resize decisions are -// taken through this additional cluster information. -var clusterAdditionalInfo = make(map[string]*localClusterState) +var ( + // clusterAdditionalInfo contains information regarding if resize is + // supported in the particular cluster and subvolumegroup is + // created or not. + // Subvolumegroup creation and volume resize decisions are + // taken through this additional cluster information. + clusterAdditionalInfo = make(map[string]*localClusterState) + // clusterAdditionalInfoMutex is used to protect against + // concurrent writes. + clusterAdditionalInfoMutex = sync.Mutex{} +) // Subvolume holds subvolume information. This includes only the needed members // from fsAdmin.SubVolumeInfo. @@ -214,6 +220,8 @@ type localClusterState struct { func newLocalClusterState(clusterID string) { // verify if corresponding clusterID key is present in the map, // and if not, initialize with default values(false). + clusterAdditionalInfoMutex.Lock() + defer clusterAdditionalInfoMutex.Unlock() if _, keyPresent := clusterAdditionalInfo[clusterID]; !keyPresent { clusterAdditionalInfo[clusterID] = &localClusterState{} clusterAdditionalInfo[clusterID].subVolumeGroupsCreated = make(map[string]bool)