Fail to start server if detected cross-device mounts. (#4807)

Fixes #4764
This commit is contained in:
Harshavardhana
2017-08-15 15:10:50 -07:00
committed by Dee Koder
parent 3d21119ec8
commit 879cef37a1
10 changed files with 487 additions and 3 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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)

View File

@@ -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 {