fix: throw appropriate errors when all disks fail (#13820)

when all disks fail with same error, fail server
startup anyways - we cannot proceed.

fixes #13818
This commit is contained in:
Harshavardhana 2021-12-03 09:25:17 -08:00 committed by GitHub
parent 1df1517449
commit a7c430355a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 6 deletions

View File

@ -188,13 +188,17 @@ func connectLoadInitFormats(retryCount int, firstDisk bool, endpoints Endpoints,
for i, err := range errs { for i, err := range errs {
if err != nil { if err != nil {
if err == errDiskNotFound && retryCount >= 5 { if err == errDiskNotFound && retryCount >= 5 {
logger.Info("Unable to connect to %s: %v", endpoints[i], isServerResolvable(endpoints[i], time.Second)) logger.Error("Unable to connect to %s: %v", endpoints[i], isServerResolvable(endpoints[i], time.Second))
} else { } else {
logger.Info("Unable to use the drive %s: %v", endpoints[i], err) logger.Error("Unable to use the drive %s: %v", endpoints[i], err)
} }
} }
} }
if err := checkDiskFatalErrs(errs); err != nil {
return nil, nil, err
}
// Attempt to load all `format.json` from all disks. // Attempt to load all `format.json` from all disks.
formatConfigs, sErrs := loadFormatErasureAll(storageDisks, false) formatConfigs, sErrs := loadFormatErasureAll(storageDisks, false)
// Check if we have // Check if we have
@ -202,7 +206,7 @@ func connectLoadInitFormats(retryCount int, firstDisk bool, endpoints Endpoints,
// print the error, nonetheless, which is perhaps unhandled // print the error, nonetheless, which is perhaps unhandled
if sErr != errUnformattedDisk && sErr != errDiskNotFound && retryCount >= 5 { if sErr != errUnformattedDisk && sErr != errDiskNotFound && retryCount >= 5 {
if sErr != nil { if sErr != nil {
logger.Info("Unable to read 'format.json' from %s: %v\n", endpoints[i], sErr) logger.Error("Unable to read 'format.json' from %s: %v\n", endpoints[i], sErr)
} }
} }
} }

View File

@ -1092,6 +1092,33 @@ func (s *storageRESTServer) VerifyFileHandler(w http.ResponseWriter, r *http.Req
encoder.Encode(vresp) encoder.Encode(vresp)
} }
func checkDiskFatalErrs(errs []error) error {
// This returns a common error if all errors are
// same errors, then there is no point starting
// the server.
if countErrs(errs, errUnsupportedDisk) == len(errs) {
return errUnsupportedDisk
}
if countErrs(errs, errDiskAccessDenied) == len(errs) {
return errDiskAccessDenied
}
if countErrs(errs, errFileAccessDenied) == len(errs) {
return errDiskAccessDenied
}
if countErrs(errs, errDiskNotDir) == len(errs) {
return errDiskNotDir
}
if countErrs(errs, errFaultyDisk) == len(errs) {
return errFaultyDisk
}
return nil
}
// A single function to write certain errors to be fatal // A single function to write certain errors to be fatal
// or informative based on the `exit` flag, please look // or informative based on the `exit` flag, please look
// at each implementation of error for added hints. // at each implementation of error for added hints.
@ -1101,8 +1128,6 @@ func (s *storageRESTServer) VerifyFileHandler(w http.ResponseWriter, r *http.Req
// Do not like it :-( // Do not like it :-(
func logFatalErrs(err error, endpoint Endpoint, exit bool) { func logFatalErrs(err error, endpoint Endpoint, exit bool) {
switch { switch {
case errors.Is(err, errMinDiskSize):
logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(err.Error()), "Unable to initialize backend")
case errors.Is(err, errUnsupportedDisk): case errors.Is(err, errUnsupportedDisk):
var hint string var hint string
if endpoint.URL != nil { if endpoint.URL != nil {
@ -1119,7 +1144,7 @@ func logFatalErrs(err error, endpoint Endpoint, exit bool) {
hint = "Disks are not directories, MinIO erasure coding needs directories" hint = "Disks are not directories, MinIO erasure coding needs directories"
} }
logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(hint), "Unable to initialize backend") logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(hint), "Unable to initialize backend")
case errors.Is(err, errFileAccessDenied): case errors.Is(err, errDiskAccessDenied):
// Show a descriptive error with a hint about how to fix it. // Show a descriptive error with a hint about how to fix it.
var username string var username string
if u, err := user.Current(); err == nil { if u, err := user.Current(); err == nil {

View File

@ -271,10 +271,23 @@ func newXLStorage(ep Endpoint) (*xlStorage, error) {
filePath := pathJoin(p.diskPath, minioMetaTmpBucket, tmpFile) filePath := pathJoin(p.diskPath, minioMetaTmpBucket, tmpFile)
w, err := OpenFileDirectIO(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666) w, err := OpenFileDirectIO(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666)
if err != nil { if err != nil {
switch {
case isSysErrInvalidArg(err):
return p, errUnsupportedDisk
case osIsPermission(err):
return p, errDiskAccessDenied
case isSysErrIO(err):
return p, errFaultyDisk
case isSysErrNotDir(err):
return p, errDiskNotDir
}
return p, err return p, err
} }
if _, err = w.Write(alignedBuf); err != nil { if _, err = w.Write(alignedBuf); err != nil {
w.Close() w.Close()
if isSysErrInvalidArg(err) {
return p, errUnsupportedDisk
}
return p, err return p, err
} }
w.Close() w.Close()