Fix PUT bucket notification deadlocks (#5734)

This PR fixes two different variant of deadlocks in
notification.

- holding write lock on the bucket competing with read lock
- holding competing locks on read/save notification config
master
Harshavardhana 7 years ago committed by Dee Koder
parent 35b3913d22
commit ef61b36c5a
  1. 8
      cmd/bucket-notification-handlers.go
  2. 16
      cmd/notification.go

@ -138,14 +138,6 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter,
return return
} }
// Acquire a write lock on bucket before modifying its configuration.
bucketLock := globalNSMutex.NewNSLock(bucketName, "")
if err = bucketLock.GetLock(globalOperationTimeout); err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return
}
defer bucketLock.Unlock()
if err = saveNotificationConfig(objectAPI, bucketName, config); err != nil { if err = saveNotificationConfig(objectAPI, bucketName, config); err != nil {
writeErrorResponse(w, toAPIErrorCode(err), r.URL) writeErrorResponse(w, toAPIErrorCode(err), r.URL)
return return

@ -496,14 +496,6 @@ func readConfig(objAPI ObjectLayer, configFile string) (*bytes.Buffer, error) {
func readNotificationConfig(objAPI ObjectLayer, bucketName string) (*event.Config, error) { func readNotificationConfig(objAPI ObjectLayer, bucketName string) (*event.Config, error) {
// Construct path to notification.xml for the given bucket. // Construct path to notification.xml for the given bucket.
configFile := path.Join(bucketConfigPrefix, bucketName, bucketNotificationConfig) configFile := path.Join(bucketConfigPrefix, bucketName, bucketNotificationConfig)
// Get read lock.
objLock := globalNSMutex.NewNSLock(minioMetaBucket, configFile)
if err := objLock.GetRLock(globalOperationTimeout); err != nil {
return nil, err
}
defer objLock.RUnlock()
reader, err := readConfig(objAPI, configFile) reader, err := readConfig(objAPI, configFile)
if err != nil { if err != nil {
return nil, err return nil, err
@ -519,14 +511,6 @@ func saveNotificationConfig(objAPI ObjectLayer, bucketName string, config *event
} }
configFile := path.Join(bucketConfigPrefix, bucketName, bucketNotificationConfig) configFile := path.Join(bucketConfigPrefix, bucketName, bucketNotificationConfig)
// Get write lock.
objLock := globalNSMutex.NewNSLock(minioMetaBucket, configFile)
if err := objLock.GetLock(globalOperationTimeout); err != nil {
return err
}
defer objLock.Unlock()
return saveConfig(objAPI, configFile, data) return saveConfig(objAPI, configFile, data)
} }

Loading…
Cancel
Save