fix: for containers use root-disk detection cleverly (#11593)

root-disk implemented currently had issues where root
disk partitions getting modified might race and provide
incorrect results, to avoid this lets rely again back on
DeviceID and match it instead.

In-case of containers `/data` is one such extra entity that
needs to be verified for root disk, due to how 'overlay'
filesystem works and the 'overlay' presents a completely
different 'device' id - using `/data` as another entity
for fallback helps because our containers describe 'VOLUME'
parameter that allows containers to automatically have a
virtual `/data` that points to the container root path this
can either be at `/` or `/var/lib/` (on different partition)
This commit is contained in:
Harshavardhana 2021-02-22 10:32:21 -08:00 committed by GitHub
parent c31d2c3fdc
commit 18ec933085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 105 additions and 38 deletions

View File

@ -1,2 +1,10 @@
.git .git
.github .github
docs
CREDITS
default.etcd
browser
*.gz
*.tar.gz
*.bzip2
*.zip

View File

@ -6,8 +6,6 @@ LABEL maintainer="MinIO Inc <dev@min.io>"
COPY dockerscripts/docker-entrypoint.sh /usr/bin/ COPY dockerscripts/docker-entrypoint.sh /usr/bin/
COPY minio /usr/bin/ COPY minio /usr/bin/
COPY CREDITS /licenses/CREDITS
COPY LICENSE /licenses/LICENSE
ENV MINIO_UPDATE=off \ ENV MINIO_UPDATE=off \
MINIO_ACCESS_KEY_FILE=access_key \ MINIO_ACCESS_KEY_FILE=access_key \
@ -17,10 +15,9 @@ ENV MINIO_UPDATE=off \
MINIO_KMS_MASTER_KEY_FILE=kms_master_key \ MINIO_KMS_MASTER_KEY_FILE=kms_master_key \
MINIO_SSE_MASTER_KEY_FILE=sse_master_key MINIO_SSE_MASTER_KEY_FILE=sse_master_key
RUN \ RUN microdnf update --nodocs
microdnf update --nodocs && \ RUN microdnf install curl ca-certificates shadow-utils util-linux --nodocs
microdnf install curl ca-certificates shadow-utils util-linux --nodocs && \ RUN microdnf clean all && \
microdnf clean all && \
chmod +x /usr/bin/minio && \ chmod +x /usr/bin/minio && \
chmod +x /usr/bin/docker-entrypoint.sh chmod +x /usr/bin/docker-entrypoint.sh

View File

@ -81,9 +81,8 @@ docker-hotfix: hotfix checks
@echo "Building minio docker image '$(TAG)'" @echo "Building minio docker image '$(TAG)'"
@docker build -t $(TAG) . -f Dockerfile.dev @docker build -t $(TAG) . -f Dockerfile.dev
docker: checks docker: build checks
@echo "Building minio docker image '$(TAG)'" @echo "Building minio docker image '$(TAG)'"
@GOOS=linux GO111MODULE=on CGO_ENABLED=0 go build -tags kqueue -trimpath --ldflags "$(LDFLAGS)" -o $(PWD)/minio 1>/dev/null
@docker build -t $(TAG) . -f Dockerfile.dev @docker build -t $(TAG) . -f Dockerfile.dev
# Builds minio and installs it to $GOPATH/bin. # Builds minio and installs it to $GOPATH/bin.

View File

@ -217,9 +217,35 @@ func newXLStorage(ep Endpoint) (*xlStorage, error) {
if env.Get("MINIO_CI_CD", "") != "" { if env.Get("MINIO_CI_CD", "") != "" {
rootDisk = true rootDisk = true
} else { } else {
rootDisk, err = disk.IsRootDisk(path, "/") if IsDocker() || IsKubernetes() {
if err != nil { // Start with overlay "/" to check if
return nil, err // possible the path has device id as
// "overlay" that would mean the path
// is emphemeral and we should treat it
// as root disk from the baremetal
// terminology.
rootDisk, err = disk.IsRootDisk(path, "/")
if err != nil {
return nil, err
}
if !rootDisk {
// No root disk was found, its possible that
// path is referenced at "/data" which has
// different device ID that points to the original
// "/" on the host system, fall back to that instead
// to verify of the device id is same.
rootDisk, err = disk.IsRootDisk(path, "/data")
if err != nil {
return nil, err
}
}
} else {
// On baremetal setups its always "/" is the root disk.
rootDisk, err = disk.IsRootDisk(path, "/")
if err != nil {
return nil, err
}
} }
} }

View File

@ -30,21 +30,3 @@ type Info struct {
Ffree uint64 Ffree uint64
FSType string FSType string
} }
// SameDisk reports whether di1 and di2 describe the same disk.
func SameDisk(di1, di2 Info) bool {
if di1.Total != di2.Total {
// disk total size different
return false
}
if di1.Files != di2.Files {
// disk total inodes different
return false
}
// returns true only if Used, Free are same, then its the same disk.
// we are deliberately not using free inodes as that is unreliable
// due the fact that Ffree can vary even for temporary files
return di1.Used == di2.Used && di1.Free == di2.Free
}

39
pkg/disk/disk_unix.go Normal file
View File

@ -0,0 +1,39 @@
// +build !windows
/*
* MinIO Cloud Storage, (C) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package disk
import (
"syscall"
)
// SameDisk reports whether di1 and di2 describe the same disk.
func SameDisk(disk1, disk2 string) (bool, error) {
st1 := syscall.Stat_t{}
st2 := syscall.Stat_t{}
if err := syscall.Stat(disk1, &st1); err != nil {
return false, err
}
if err := syscall.Stat(disk2, &st2); err != nil {
return false, err
}
return st1.Dev == st2.Dev, nil
}

24
pkg/disk/disk_windows.go Normal file
View File

@ -0,0 +1,24 @@
// +build windows
/*
* MinIO Cloud Storage, (C) 2021 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package disk
// SameDisk reports whether di1 and di2 describe the same disk.
func SameDisk(disk1, disk2 string) (bool, error) {
return false, nil
}

View File

@ -25,13 +25,5 @@ func IsRootDisk(diskPath string, rootDisk string) (bool, error) {
// On windows this function is not implemented. // On windows this function is not implemented.
return false, nil return false, nil
} }
info, err := GetInfo(diskPath) return SameDisk(diskPath, rootDisk)
if err != nil {
return false, err
}
rootInfo, err := GetInfo(rootDisk)
if err != nil {
return false, err
}
return SameDisk(info, rootInfo), nil
} }