diff --git a/cmd/config/errors.go b/cmd/config/errors.go index cc9305cf2..1122e5224 100644 --- a/cmd/config/errors.go +++ b/cmd/config/errors.go @@ -169,6 +169,12 @@ Example 1: $ minio server /data/minio/`, ) + ErrUnsupportedBackend = newErrFn( + "Unable to write to the backend", + "Please ensure your disk supports O_DIRECT", + "", + ) + ErrUnableToWriteInBackend = newErrFn( "Unable to write to the backend", "Please ensure MinIO binary has write permissions for the backend", diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index 9c8c124cb..9bafc37a0 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -131,8 +131,12 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) { var err error if fsPath, err = getValidPath(fsPath); err != nil { if err == errMinDiskSize { - return nil, err + return nil, config.ErrUnableToWriteInBackend(err).Hint(err.Error()) + } else if err == errUnsupportedDisk { + hint := fmt.Sprintf("'%s' does not support O_DIRECT flags, refusing to use", fsPath) + return nil, config.ErrUnsupportedBackend(err).Hint(hint) } + // 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/posix-errors.go b/cmd/posix-errors.go index d4f6e76af..652333260 100644 --- a/cmd/posix-errors.go +++ b/cmd/posix-errors.go @@ -38,6 +38,11 @@ func isSysErrNoSpace(err error) bool { return errors.Is(err, syscall.ENOSPC) } +// Invalid argument, unsupported flags such as O_DIRECT +func isSysErrInvalidArg(err error) bool { + return errors.Is(err, syscall.EINVAL) +} + // Input/output error func isSysErrIO(err error) bool { return errors.Is(err, syscall.EIO) diff --git a/cmd/posix.go b/cmd/posix.go index 898386309..3c91cd72b 100644 --- a/cmd/posix.go +++ b/cmd/posix.go @@ -177,13 +177,20 @@ func getValidPath(path string) (string, error) { // check if backend is writable. var rnd [8]byte _, _ = rand.Read(rnd[:]) + fn := pathJoin(path, ".writable-check-"+hex.EncodeToString(rnd[:])+".tmp") - file, err := disk.OpenFileDirectIO(fn, os.O_CREATE, 0600) + defer os.Remove(fn) + + // open file in direct I/O and use default umask, this also verifies + // if direct i/o failed. + file, err := disk.OpenFileDirectIO(fn, os.O_CREATE|os.O_EXCL, 0666) if err != nil { + if isSysErrInvalidArg(err) { + return path, errUnsupportedDisk + } return path, err } file.Close() - os.Remove(fn) return path, nil } @@ -1279,6 +1286,8 @@ func (s *posix) CreateFile(volume, path string, fileSize int64, r io.Reader) (er return errFileAccessDenied case isSysErrIO(err): return errFaultyDisk + case isSysErrInvalidArg(err): + return errUnsupportedDisk default: return err } diff --git a/cmd/server-main.go b/cmd/server-main.go index 210f8f745..25662da00 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -215,7 +215,11 @@ func initSafeMode() (err error) { logger.Info("Waiting for all MinIO sub-systems to be initialized.. trying to acquire lock") continue } - logger.Info("Waiting for all MinIO sub-systems to be initialized.. lock acquired") + + // These messages only meant primarily for distributed setup, so only log during distributed setup. + if globalIsDistXL { + logger.Info("Waiting for all MinIO sub-systems to be initialized.. lock acquired") + } // Migrate all backend configs to encrypted backend configs, optionally // handles rotating keys for encryption, if there is any retriable failure @@ -225,6 +229,10 @@ func initSafeMode() (err error) { // if all sub-systems initialized successfully return right away if err = initAllSubsystems(newObject); err == nil { // All successful return. + if globalIsDistXL { + // These messages only meant primarily for distributed setup, so only log during distributed setup. + logger.Info("All MinIO sub-systems initialized successfully") + } return nil } } diff --git a/cmd/storage-errors.go b/cmd/storage-errors.go index 695c1f8c1..6a674e1cc 100644 --- a/cmd/storage-errors.go +++ b/cmd/storage-errors.go @@ -25,6 +25,9 @@ var errCorruptedFormat = StorageErr("corrupted backend format, please join https // errUnformattedDisk - unformatted disk found. var errUnformattedDisk = StorageErr("unformatted disk found") +// errUnsupporteDisk - when disk does not support O_DIRECT flag. +var errUnsupportedDisk = StorageErr("disk does not support O_DIRECT") + // errDiskFull - cannot create volume or files when disk is full. var errDiskFull = StorageErr("disk path full") @@ -81,7 +84,7 @@ var errBitrotHashAlgoInvalid = StorageErr("bit-rot hash algorithm is invalid") var errCrossDeviceLink = StorageErr("Rename across devices not allowed, please fix your backend configuration") // errMinDiskSize - cannot create volume or files when disk size is less than threshold. -var errMinDiskSize = StorageErr("The disk size is less than the minimum threshold") +var errMinDiskSize = StorageErr("The disk size is less than 900MiB threshold") // errLessData - returned when less data available than what was requested. var errLessData = StorageErr("less data available than what was requested") diff --git a/cmd/storage-rest-server.go b/cmd/storage-rest-server.go index 463412d20..2d3e69ae7 100644 --- a/cmd/storage-rest-server.go +++ b/cmd/storage-rest-server.go @@ -738,6 +738,12 @@ func registerStorageRESTHandlers(router *mux.Router, endpointZones EndpointZones } storage, err := newPosix(endpoint.Path) if err != nil { + if err == errMinDiskSize { + logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(err.Error()), "Unable to initialize backend") + } else if err == errUnsupportedDisk { + hint := fmt.Sprintf("'%s' does not support O_DIRECT flags, refusing to use", endpoint.Path) + logger.Fatal(config.ErrUnsupportedBackend(err).Hint(hint), "Unable to initialize backend") + } // Show a descriptive error with a hint about how to fix it. var username string if u, err := user.Current(); err == nil { @@ -747,7 +753,7 @@ func registerStorageRESTHandlers(router *mux.Router, endpointZones EndpointZones } hint := fmt.Sprintf("Run the following command to add the convenient permissions: `sudo chown %s %s && sudo chmod u+rxw %s`", username, endpoint.Path, endpoint.Path) - logger.Fatal(config.ErrUnableToWriteInBackend(err).Msg(err.Error()).Hint(hint), + logger.Fatal(config.ErrUnableToWriteInBackend(err).Hint(hint), "Unable to initialize posix backend") }