From a7c430355a0a9c22c51871554bfb60a21e4e0047 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 3 Dec 2021 09:25:17 -0800 Subject: [PATCH] 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 --- cmd/prepare-storage.go | 10 +++++++--- cmd/storage-rest-server.go | 31 ++++++++++++++++++++++++++++--- cmd/xl-storage.go | 13 +++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/cmd/prepare-storage.go b/cmd/prepare-storage.go index de1c6d4a3..f7fd82081 100644 --- a/cmd/prepare-storage.go +++ b/cmd/prepare-storage.go @@ -188,13 +188,17 @@ func connectLoadInitFormats(retryCount int, firstDisk bool, endpoints Endpoints, for i, err := range errs { if err != nil { 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 { - 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. formatConfigs, sErrs := loadFormatErasureAll(storageDisks, false) // Check if we have @@ -202,7 +206,7 @@ func connectLoadInitFormats(retryCount int, firstDisk bool, endpoints Endpoints, // print the error, nonetheless, which is perhaps unhandled if sErr != errUnformattedDisk && sErr != errDiskNotFound && retryCount >= 5 { 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) } } } diff --git a/cmd/storage-rest-server.go b/cmd/storage-rest-server.go index 56b3c82f6..fd9439580 100644 --- a/cmd/storage-rest-server.go +++ b/cmd/storage-rest-server.go @@ -1092,6 +1092,33 @@ func (s *storageRESTServer) VerifyFileHandler(w http.ResponseWriter, r *http.Req 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 // or informative based on the `exit` flag, please look // 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 :-( func logFatalErrs(err error, endpoint Endpoint, exit bool) { switch { - case errors.Is(err, errMinDiskSize): - logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(err.Error()), "Unable to initialize backend") case errors.Is(err, errUnsupportedDisk): var hint string 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" } 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. var username string if u, err := user.Current(); err == nil { diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index 84d65c3f4..a5b07ff50 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -271,10 +271,23 @@ func newXLStorage(ep Endpoint) (*xlStorage, error) { filePath := pathJoin(p.diskPath, minioMetaTmpBucket, tmpFile) w, err := OpenFileDirectIO(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0666) 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 } if _, err = w.Write(alignedBuf); err != nil { w.Close() + if isSysErrInvalidArg(err) { + return p, errUnsupportedDisk + } return p, err } w.Close()