From 254b05e3144f4031b9b5310e24a47e7ee1c68a59 Mon Sep 17 00:00:00 2001 From: Aditya Manthramurthy Date: Mon, 22 Jan 2018 18:09:12 -0800 Subject: [PATCH] Fix locking in some admin APIs: (#5438) - read lock for get config - write lock for update creds - write lock for format file --- cmd/admin-handlers.go | 19 +++++++++++++++++++ cmd/admin-heal-ops.go | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 42474e723..fb9d42840 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -575,6 +575,16 @@ func (a adminAPIHandlers) GetConfigHandler(w http.ResponseWriter, r *http.Reques return } + // Take a read lock on minio/config.json. NB minio is a + // reserved bucket name and wouldn't conflict with normal + // object operations. + configLock := globalNSMutex.NewNSLock(minioReservedBucket, minioConfigFile) + if configLock.GetRLock(globalObjectTimeout) != nil { + writeErrorResponseJSON(w, ErrOperationTimedOut, r.URL) + return + } + defer configLock.RUnlock() + // Get config.json - in distributed mode, the configuration // occurring on a quorum of the servers is returned. configBytes, err := getPeerConfig(globalAdminPeers) @@ -784,6 +794,15 @@ func (a adminAPIHandlers) UpdateCredentialsHandler(w http.ResponseWriter, return } + // Take a lock on minio/config.json. Prevents concurrent + // config file/credentials updates. + configLock := globalNSMutex.NewNSLock(minioReservedBucket, minioConfigFile) + if configLock.GetLock(globalObjectTimeout) != nil { + writeErrorResponseJSON(w, ErrOperationTimedOut, r.URL) + return + } + defer configLock.Unlock() + // Notify all other Minio peers to update credentials updateErrs := updateCredsOnPeers(creds) for peer, err := range updateErrs { diff --git a/cmd/admin-heal-ops.go b/cmd/admin-heal-ops.go index 5d7dca68b..76ad2e1ce 100644 --- a/cmd/admin-heal-ops.go +++ b/cmd/admin-heal-ops.go @@ -528,6 +528,13 @@ func (h *healSequence) healDiskFormat() error { return errServerNotInitialized } + // Acquire lock on format.json + formatLock := globalNSMutex.NewNSLock(minioMetaBucket, formatConfigFile) + if err := formatLock.GetLock(globalHealingTimeout); err != nil { + return errFnHealFromAPIErr(err) + } + defer formatLock.Unlock() + // Create a new set of storage instances to heal format.json. bootstrapDisks, err := initStorageDisks(globalEndpoints) if err != nil {