Report correct error when O_DIRECT is not supported (#9545)

fixes #9537
This commit is contained in:
Harshavardhana 2020-05-07 16:12:16 -07:00 committed by GitHub
parent 0674c0075e
commit 2dc46cb153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 6 deletions

View File

@ -169,6 +169,12 @@ Example 1:
$ minio server /data/minio/`, $ minio server /data/minio/`,
) )
ErrUnsupportedBackend = newErrFn(
"Unable to write to the backend",
"Please ensure your disk supports O_DIRECT",
"",
)
ErrUnableToWriteInBackend = newErrFn( ErrUnableToWriteInBackend = newErrFn(
"Unable to write to the backend", "Unable to write to the backend",
"Please ensure MinIO binary has write permissions for the backend", "Please ensure MinIO binary has write permissions for the backend",

View File

@ -131,8 +131,12 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
var err error var err error
if fsPath, err = getValidPath(fsPath); err != nil { if fsPath, err = getValidPath(fsPath); err != nil {
if err == errMinDiskSize { 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. // 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

@ -38,6 +38,11 @@ func isSysErrNoSpace(err error) bool {
return errors.Is(err, syscall.ENOSPC) 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 // Input/output error
func isSysErrIO(err error) bool { func isSysErrIO(err error) bool {
return errors.Is(err, syscall.EIO) return errors.Is(err, syscall.EIO)

View File

@ -177,13 +177,20 @@ func getValidPath(path string) (string, error) {
// check if backend is writable. // check if backend is writable.
var rnd [8]byte var rnd [8]byte
_, _ = rand.Read(rnd[:]) _, _ = rand.Read(rnd[:])
fn := pathJoin(path, ".writable-check-"+hex.EncodeToString(rnd[:])+".tmp") 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 err != nil {
if isSysErrInvalidArg(err) {
return path, errUnsupportedDisk
}
return path, err return path, err
} }
file.Close() file.Close()
os.Remove(fn)
return path, nil return path, nil
} }
@ -1279,6 +1286,8 @@ func (s *posix) CreateFile(volume, path string, fileSize int64, r io.Reader) (er
return errFileAccessDenied return errFileAccessDenied
case isSysErrIO(err): case isSysErrIO(err):
return errFaultyDisk return errFaultyDisk
case isSysErrInvalidArg(err):
return errUnsupportedDisk
default: default:
return err return err
} }

View File

@ -215,7 +215,11 @@ func initSafeMode() (err error) {
logger.Info("Waiting for all MinIO sub-systems to be initialized.. trying to acquire lock") logger.Info("Waiting for all MinIO sub-systems to be initialized.. trying to acquire lock")
continue continue
} }
// 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") logger.Info("Waiting for all MinIO sub-systems to be initialized.. lock acquired")
}
// Migrate all backend configs to encrypted backend configs, optionally // Migrate all backend configs to encrypted backend configs, optionally
// handles rotating keys for encryption, if there is any retriable failure // 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 all sub-systems initialized successfully return right away
if err = initAllSubsystems(newObject); err == nil { if err = initAllSubsystems(newObject); err == nil {
// All successful return. // 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 return nil
} }
} }

View File

@ -25,6 +25,9 @@ var errCorruptedFormat = StorageErr("corrupted backend format, please join https
// errUnformattedDisk - unformatted disk found. // errUnformattedDisk - unformatted disk found.
var errUnformattedDisk = StorageErr("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. // errDiskFull - cannot create volume or files when disk is full.
var errDiskFull = StorageErr("disk path 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") 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. // 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. // errLessData - returned when less data available than what was requested.
var errLessData = StorageErr("less data available than what was requested") var errLessData = StorageErr("less data available than what was requested")

View File

@ -738,6 +738,12 @@ func registerStorageRESTHandlers(router *mux.Router, endpointZones EndpointZones
} }
storage, err := newPosix(endpoint.Path) storage, err := newPosix(endpoint.Path)
if err != nil { 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. // 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 {
@ -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`", 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) 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") "Unable to initialize posix backend")
} }