mirror of
https://github.com/minio/minio.git
synced 2025-11-07 04:42:56 -05:00
Fail to start server if detected cross-device mounts. (#4807)
Fixes #4764
This commit is contained in:
committed by
Dee Koder
parent
3d21119ec8
commit
879cef37a1
@@ -21,11 +21,13 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio-go/pkg/set"
|
||||
"github.com/minio/minio/pkg/mountinfo"
|
||||
)
|
||||
|
||||
// EndpointType - enum for endpoint type.
|
||||
@@ -99,7 +101,8 @@ func NewEndpoint(arg string) (ep Endpoint, e error) {
|
||||
return ep, fmt.Errorf("invalid URL endpoint format")
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
var host, port string
|
||||
host, port, err = net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "missing port in address") {
|
||||
return ep, fmt.Errorf("invalid URL endpoint format: %s", err)
|
||||
@@ -226,6 +229,22 @@ func NewEndpointList(args ...string) (endpoints EndpointList, err error) {
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// Checks if there are any cross device mounts.
|
||||
func checkCrossDeviceMounts(endpoints EndpointList) (err error) {
|
||||
var absPaths []string
|
||||
for _, endpoint := range endpoints {
|
||||
if endpoint.IsLocal {
|
||||
var absPath string
|
||||
absPath, err = filepath.Abs(endpoint.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
absPaths = append(absPaths, absPath)
|
||||
}
|
||||
}
|
||||
return mountinfo.CheckCrossDevice(absPaths)
|
||||
}
|
||||
|
||||
// CreateEndpoints - validates and creates new endpoints for given args.
|
||||
func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, SetupType, error) {
|
||||
var endpoints EndpointList
|
||||
@@ -246,13 +265,16 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
|
||||
if err != nil {
|
||||
return serverAddr, endpoints, setupType, err
|
||||
}
|
||||
|
||||
if endpoint.Type() != PathEndpointType {
|
||||
return serverAddr, endpoints, setupType, fmt.Errorf("use path style endpoint for FS setup")
|
||||
}
|
||||
|
||||
endpoints = append(endpoints, endpoint)
|
||||
setupType = FSSetupType
|
||||
|
||||
// Check for cross device mounts if any.
|
||||
if err = checkCrossDeviceMounts(endpoints); err != nil {
|
||||
return serverAddr, endpoints, setupType, err
|
||||
}
|
||||
return serverAddr, endpoints, setupType, nil
|
||||
}
|
||||
|
||||
@@ -261,6 +283,11 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
|
||||
return serverAddr, endpoints, setupType, err
|
||||
}
|
||||
|
||||
// Check for cross device mounts if any.
|
||||
if err = checkCrossDeviceMounts(endpoints); err != nil {
|
||||
return serverAddr, endpoints, setupType, err
|
||||
}
|
||||
|
||||
// Return XL setup when all endpoints are path style.
|
||||
if endpoints[0].Type() == PathEndpointType {
|
||||
setupType = XLSetupType
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
pathutil "path"
|
||||
@@ -360,6 +361,9 @@ func fsRenameFile(sourcePath, destPath string) error {
|
||||
return traceError(err)
|
||||
}
|
||||
if err := os.Rename((sourcePath), (destPath)); err != nil {
|
||||
if isSysErrCrossDevice(err) {
|
||||
return traceError(fmt.Errorf("%s (%s)->(%s)", errCrossDeviceLink, sourcePath, destPath))
|
||||
}
|
||||
return traceError(err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -118,3 +118,10 @@ func isSysErrHandleInvalid(err error) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isSysErrCrossDevice(err error) bool {
|
||||
if e, ok := err.(*os.LinkError); ok {
|
||||
return e.Err == syscall.EXDEV
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ func newPosix(path string) (StorageAPI, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st := &posix{
|
||||
diskPath: diskPath,
|
||||
// 1MiB buffer pool for posix internal operations.
|
||||
|
||||
@@ -91,6 +91,7 @@ func serverHandleCmdArgs(ctx *cli.Context) {
|
||||
|
||||
var setupType SetupType
|
||||
var err error
|
||||
|
||||
globalMinioAddr, globalEndpoints, setupType, err = CreateEndpoints(serverAddr, ctx.Args()...)
|
||||
fatalIf(err, "Invalid command line arguments server=‘%s’, args=%s", serverAddr, ctx.Args())
|
||||
globalMinioHost, globalMinioPort = mustSplitHostPort(globalMinioAddr)
|
||||
|
||||
@@ -83,6 +83,9 @@ var errFileAccessDenied = errors.New("file access denied")
|
||||
// verification is empty or invalid.
|
||||
var errBitrotHashAlgoInvalid = errors.New("bit-rot hash algorithm is invalid")
|
||||
|
||||
// errCrossDeviceLink - rename across devices not allowed.
|
||||
var errCrossDeviceLink = errors.New("Rename across devices not allowed, please fix your backend configuration")
|
||||
|
||||
// hashMisMatchError - represents a bit-rot hash verification failure
|
||||
// error.
|
||||
type hashMismatchError struct {
|
||||
|
||||
Reference in New Issue
Block a user