Fix writing 'format.json' and make it atomic (#8296)

- Choose a unique uuid such that under situations of duplicate
  mounts we do not append to an existing json entry.
- Avoid AppendFile instead use WriteAll() to write the entire
  byte array atomically.
This commit is contained in:
Harshavardhana 2019-09-24 18:47:26 -07:00 committed by GitHub
parent be70ef59e7
commit c8fbc94329
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 18 deletions

View file

@ -20,9 +20,6 @@ package cmd
const (
// Format config file carries backend format specific details.
formatConfigFile = "format.json"
// Format config tmp file carries backend format.
formatConfigFileTmp = "format.json.tmp"
)
const (

View file

@ -17,6 +17,7 @@
package cmd
import (
"bytes"
"context"
"encoding/json"
"fmt"
@ -291,16 +292,6 @@ func formatXLMigrateV2ToV3(export string) error {
return ioutil.WriteFile(formatPath, b, 0644)
}
// Returns true, if one of the errors is non-nil and is Unformatted disk.
func hasAnyErrorsUnformatted(errs []error) bool {
for _, err := range errs {
if err != nil && err == errUnformattedDisk {
return true
}
}
return false
}
// countErrs - count a specific error.
func countErrs(errs []error, err error) int {
var i = 0
@ -367,16 +358,18 @@ func saveFormatXL(disk StorageAPI, format interface{}) error {
return err
}
tmpFormatJSON := mustGetUUID() + ".json"
// Purge any existing temporary file, okay to ignore errors here.
defer disk.DeleteFile(minioMetaBucket, formatConfigFileTmp)
defer disk.DeleteFile(minioMetaBucket, tmpFormatJSON)
// Append file `format.json.tmp`.
if err = disk.AppendFile(minioMetaBucket, formatConfigFileTmp, formatBytes); err != nil {
if err = disk.WriteAll(minioMetaBucket, tmpFormatJSON, bytes.NewReader(formatBytes)); err != nil {
return err
}
// Rename file `format.json.tmp` --> `format.json`.
return disk.RenameFile(minioMetaBucket, formatConfigFileTmp, minioMetaBucket, formatConfigFile)
// Rename file `uuid.json` --> `format.json`.
return disk.RenameFile(minioMetaBucket, tmpFormatJSON, minioMetaBucket, formatConfigFile)
}
var ignoredHiddenDirectories = []string{

View file

@ -1492,7 +1492,7 @@ func (s *xlSets) HealFormat(ctx context.Context, dryRun bool) (res madmin.HealRe
}
}
if !hasAnyErrorsUnformatted(sErrs) {
if countErrs(sErrs, errUnformattedDisk) == 0 {
// No unformatted disks found disks are either offline
// or online, no healing is required.
return res, errNoHealRequired