mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
info: Always refresh the root disk status (#20023)
Add root drive status in the disk info cache function, so unmounting a drive without restarting a local node reflects the correct value.
This commit is contained in:
parent
2040559f71
commit
2ec1f404ac
@ -365,7 +365,7 @@ func getLocalDisksToHeal() (disksToHeal Endpoints) {
|
|||||||
localDrives := cloneDrives(globalLocalDrives)
|
localDrives := cloneDrives(globalLocalDrives)
|
||||||
globalLocalDrivesMu.RUnlock()
|
globalLocalDrivesMu.RUnlock()
|
||||||
for _, disk := range localDrives {
|
for _, disk := range localDrives {
|
||||||
_, err := disk.GetDiskID()
|
_, err := disk.DiskInfo(context.Background(), DiskInfoOptions{})
|
||||||
if errors.Is(err, errUnformattedDisk) {
|
if errors.Is(err, errUnformattedDisk) {
|
||||||
disksToHeal = append(disksToHeal, disk.Endpoint())
|
disksToHeal = append(disksToHeal, disk.Endpoint())
|
||||||
continue
|
continue
|
||||||
@ -393,6 +393,17 @@ func healFreshDisk(ctx context.Context, z *erasureServerPools, endpoint Endpoint
|
|||||||
return fmt.Errorf("Unexpected error disk must be initialized by now after formatting: %s", endpoint)
|
return fmt.Errorf("Unexpected error disk must be initialized by now after formatting: %s", endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := disk.DiskInfo(ctx, DiskInfoOptions{})
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, errDriveIsRoot) {
|
||||||
|
// This is a root drive, ignore and move on
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !errors.Is(err, errUnformattedDisk) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent parallel erasure set healing
|
// Prevent parallel erasure set healing
|
||||||
locker := z.NewNSLock(minioMetaBucket, fmt.Sprintf("new-drive-healing/%d/%d", poolIdx, setIdx))
|
locker := z.NewNSLock(minioMetaBucket, fmt.Sprintf("new-drive-healing/%d/%d", poolIdx, setIdx))
|
||||||
lkctx, err := locker.GetLock(ctx, newDiskHealingTimeout)
|
lkctx, err := locker.GetLock(ctx, newDiskHealingTimeout)
|
||||||
|
@ -120,13 +120,6 @@ func connectEndpoint(endpoint Endpoint) (StorageAPI, *formatErasureV3, error) {
|
|||||||
|
|
||||||
format, err := loadFormatErasure(disk, false)
|
format, err := loadFormatErasure(disk, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errUnformattedDisk) {
|
|
||||||
info, derr := disk.DiskInfo(context.TODO(), DiskInfoOptions{})
|
|
||||||
if derr != nil && info.RootDisk {
|
|
||||||
disk.Close()
|
|
||||||
return nil, nil, fmt.Errorf("Drive: %s is a root drive", disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.Close()
|
disk.Close()
|
||||||
return nil, nil, fmt.Errorf("Drive: %s returned %w", disk, err) // make sure to '%w' to wrap the error
|
return nil, nil, fmt.Errorf("Drive: %s returned %w", disk, err) // make sure to '%w' to wrap the error
|
||||||
}
|
}
|
||||||
@ -230,7 +223,7 @@ func (s *erasureSets) connectDisks() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if endpoint.IsLocal && errors.Is(err, errUnformattedDisk) {
|
if endpoint.IsLocal && errors.Is(err, errUnformattedDisk) {
|
||||||
globalBackgroundHealState.pushHealLocalDisks(endpoint)
|
globalBackgroundHealState.pushHealLocalDisks(endpoint)
|
||||||
} else {
|
} else if !errors.Is(err, errDriveIsRoot) {
|
||||||
printEndpointError(endpoint, err, true)
|
printEndpointError(endpoint, err, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -102,6 +102,8 @@ func diskErrToDriveState(err error) (state string) {
|
|||||||
state = madmin.DriveStatePermission
|
state = madmin.DriveStatePermission
|
||||||
case errors.Is(err, errFaultyDisk):
|
case errors.Is(err, errFaultyDisk):
|
||||||
state = madmin.DriveStateFaulty
|
state = madmin.DriveStateFaulty
|
||||||
|
case errors.Is(err, errDriveIsRoot):
|
||||||
|
state = madmin.DriveStateRootMount
|
||||||
case err == nil:
|
case err == nil:
|
||||||
state = madmin.DriveStateOk
|
state = madmin.DriveStateOk
|
||||||
default:
|
default:
|
||||||
|
@ -98,12 +98,6 @@ func TestReleaseTagToNFromTimeConversion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDownloadURL(t *testing.T) {
|
func TestDownloadURL(t *testing.T) {
|
||||||
sci := globalIsCICD
|
|
||||||
globalIsCICD = false
|
|
||||||
defer func() {
|
|
||||||
globalIsCICD = sci
|
|
||||||
}()
|
|
||||||
|
|
||||||
minioVersion1 := releaseTimeToReleaseTag(UTCNow())
|
minioVersion1 := releaseTimeToReleaseTag(UTCNow())
|
||||||
durl := getDownloadURL(minioVersion1)
|
durl := getDownloadURL(minioVersion1)
|
||||||
if IsDocker() {
|
if IsDocker() {
|
||||||
@ -164,9 +158,6 @@ func TestUserAgent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
sci := globalIsCICD
|
|
||||||
globalIsCICD = false
|
|
||||||
|
|
||||||
if testCase.envName != "" {
|
if testCase.envName != "" {
|
||||||
t.Setenv(testCase.envName, testCase.envValue)
|
t.Setenv(testCase.envName, testCase.envValue)
|
||||||
if testCase.envName == "MESOS_CONTAINER_NAME" {
|
if testCase.envName == "MESOS_CONTAINER_NAME" {
|
||||||
@ -182,7 +173,6 @@ func TestUserAgent(t *testing.T) {
|
|||||||
if !strings.Contains(str, expectedStr) {
|
if !strings.Contains(str, expectedStr) {
|
||||||
t.Errorf("Test %d: expected: %s, got: %s", i+1, expectedStr, str)
|
t.Errorf("Test %d: expected: %s, got: %s", i+1, expectedStr, str)
|
||||||
}
|
}
|
||||||
globalIsCICD = sci
|
|
||||||
os.Unsetenv("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION")
|
os.Unsetenv("MARATHON_APP_LABEL_DCOS_PACKAGE_VERSION")
|
||||||
os.Unsetenv(testCase.envName)
|
os.Unsetenv(testCase.envName)
|
||||||
}
|
}
|
||||||
@ -190,12 +180,6 @@ func TestUserAgent(t *testing.T) {
|
|||||||
|
|
||||||
// Tests if the environment we are running is in DCOS.
|
// Tests if the environment we are running is in DCOS.
|
||||||
func TestIsDCOS(t *testing.T) {
|
func TestIsDCOS(t *testing.T) {
|
||||||
sci := globalIsCICD
|
|
||||||
globalIsCICD = false
|
|
||||||
defer func() {
|
|
||||||
globalIsCICD = sci
|
|
||||||
}()
|
|
||||||
|
|
||||||
t.Setenv("MESOS_CONTAINER_NAME", "mesos-1111")
|
t.Setenv("MESOS_CONTAINER_NAME", "mesos-1111")
|
||||||
dcos := IsDCOS()
|
dcos := IsDCOS()
|
||||||
if !dcos {
|
if !dcos {
|
||||||
@ -210,12 +194,6 @@ func TestIsDCOS(t *testing.T) {
|
|||||||
|
|
||||||
// Tests if the environment we are running is in kubernetes.
|
// Tests if the environment we are running is in kubernetes.
|
||||||
func TestIsKubernetes(t *testing.T) {
|
func TestIsKubernetes(t *testing.T) {
|
||||||
sci := globalIsCICD
|
|
||||||
globalIsCICD = false
|
|
||||||
defer func() {
|
|
||||||
globalIsCICD = sci
|
|
||||||
}()
|
|
||||||
|
|
||||||
t.Setenv("KUBERNETES_SERVICE_HOST", "10.11.148.5")
|
t.Setenv("KUBERNETES_SERVICE_HOST", "10.11.148.5")
|
||||||
kubernetes := IsKubernetes()
|
kubernetes := IsKubernetes()
|
||||||
if !kubernetes {
|
if !kubernetes {
|
||||||
|
@ -236,30 +236,17 @@ func newXLStorage(ep Endpoint, cleanUp bool) (s *xlStorage, err error) {
|
|||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := disk.GetInfo(s.drivePath, true)
|
info, rootDrive, err := getDiskInfo(s.drivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.major = info.Major
|
s.major = info.Major
|
||||||
s.minor = info.Minor
|
s.minor = info.Minor
|
||||||
s.fsType = info.FSType
|
s.fsType = info.FSType
|
||||||
|
|
||||||
if !globalIsCICD && !globalIsErasureSD {
|
if rootDrive {
|
||||||
var rootDrive bool
|
return s, errDriveIsRoot
|
||||||
if globalRootDiskThreshold > 0 {
|
|
||||||
// Use MINIO_ROOTDISK_THRESHOLD_SIZE to figure out if
|
|
||||||
// this disk is a root disk. treat those disks with
|
|
||||||
// size less than or equal to the threshold as rootDrives.
|
|
||||||
rootDrive = info.Total <= globalRootDiskThreshold
|
|
||||||
} else {
|
|
||||||
rootDrive, err = disk.IsRootDisk(s.drivePath, SlashSeparator)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rootDrive {
|
|
||||||
return s, errDriveIsRoot
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize before setting it
|
// Sanitize before setting it
|
||||||
@ -333,10 +320,11 @@ func newXLStorage(ep Endpoint, cleanUp bool) (s *xlStorage, err error) {
|
|||||||
s.diskInfoCache.InitOnce(time.Second, cachevalue.Opts{},
|
s.diskInfoCache.InitOnce(time.Second, cachevalue.Opts{},
|
||||||
func(ctx context.Context) (DiskInfo, error) {
|
func(ctx context.Context) (DiskInfo, error) {
|
||||||
dcinfo := DiskInfo{}
|
dcinfo := DiskInfo{}
|
||||||
di, err := getDiskInfo(s.drivePath)
|
di, root, err := getDiskInfo(s.drivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dcinfo, err
|
return dcinfo, err
|
||||||
}
|
}
|
||||||
|
dcinfo.RootDisk = root
|
||||||
dcinfo.Major = di.Major
|
dcinfo.Major = di.Major
|
||||||
dcinfo.Minor = di.Minor
|
dcinfo.Minor = di.Minor
|
||||||
dcinfo.Total = di.Total
|
dcinfo.Total = di.Total
|
||||||
@ -345,6 +333,10 @@ func newXLStorage(ep Endpoint, cleanUp bool) (s *xlStorage, err error) {
|
|||||||
dcinfo.UsedInodes = di.Files - di.Ffree
|
dcinfo.UsedInodes = di.Files - di.Ffree
|
||||||
dcinfo.FreeInodes = di.Ffree
|
dcinfo.FreeInodes = di.Ffree
|
||||||
dcinfo.FSType = di.FSType
|
dcinfo.FSType = di.FSType
|
||||||
|
if root {
|
||||||
|
return dcinfo, errDriveIsRoot
|
||||||
|
}
|
||||||
|
|
||||||
diskID, err := s.GetDiskID()
|
diskID, err := s.GetDiskID()
|
||||||
// Healing is 'true' when
|
// Healing is 'true' when
|
||||||
// - if we found an unformatted disk (no 'format.json')
|
// - if we found an unformatted disk (no 'format.json')
|
||||||
@ -360,10 +352,22 @@ func newXLStorage(ep Endpoint, cleanUp bool) (s *xlStorage, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getDiskInfo returns given disk information.
|
// getDiskInfo returns given disk information.
|
||||||
func getDiskInfo(drivePath string) (di disk.Info, err error) {
|
func getDiskInfo(drivePath string) (di disk.Info, rootDrive bool, err error) {
|
||||||
if err = checkPathLength(drivePath); err == nil {
|
if err = checkPathLength(drivePath); err == nil {
|
||||||
di, err = disk.GetInfo(drivePath, false)
|
di, err = disk.GetInfo(drivePath, false)
|
||||||
|
|
||||||
|
if !globalIsCICD && !globalIsErasureSD {
|
||||||
|
if globalRootDiskThreshold > 0 {
|
||||||
|
// Use MINIO_ROOTDISK_THRESHOLD_SIZE to figure out if
|
||||||
|
// this disk is a root disk. treat those disks with
|
||||||
|
// size less than or equal to the threshold as rootDrives.
|
||||||
|
rootDrive = di.Total <= globalRootDiskThreshold
|
||||||
|
} else {
|
||||||
|
rootDrive, err = disk.IsRootDisk(drivePath, SlashSeparator)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case osIsNotExist(err):
|
case osIsNotExist(err):
|
||||||
err = errDiskNotFound
|
err = errDiskNotFound
|
||||||
@ -373,7 +377,7 @@ func getDiskInfo(drivePath string) (di disk.Info, err error) {
|
|||||||
err = errFaultyDisk
|
err = errFaultyDisk
|
||||||
}
|
}
|
||||||
|
|
||||||
return di, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements stringer compatible interface.
|
// Implements stringer compatible interface.
|
||||||
|
@ -196,7 +196,7 @@ func TestXLStorageGetDiskInfo(t *testing.T) {
|
|||||||
|
|
||||||
// Check test cases.
|
// Check test cases.
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
if _, err := getDiskInfo(testCase.diskPath); err != testCase.expectedErr {
|
if _, _, err := getDiskInfo(testCase.diskPath); err != testCase.expectedErr {
|
||||||
t.Fatalf("expected: %s, got: %s", testCase.expectedErr, err)
|
t.Fatalf("expected: %s, got: %s", testCase.expectedErr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
go.sum
2
go.sum
@ -456,8 +456,6 @@ github.com/minio/kms-go/kes v0.3.0 h1:SU8VGVM/Hk9w1OiSby3OatkcojooUqIdDHl6dtM6Nk
|
|||||||
github.com/minio/kms-go/kes v0.3.0/go.mod h1:w6DeVT878qEOU3nUrYVy1WOT5H1Ig9hbDIh698NYJKY=
|
github.com/minio/kms-go/kes v0.3.0/go.mod h1:w6DeVT878qEOU3nUrYVy1WOT5H1Ig9hbDIh698NYJKY=
|
||||||
github.com/minio/kms-go/kms v0.4.0 h1:cLPZceEp+05xHotVBaeFJrgL7JcXM4lBy6PU0idkE7I=
|
github.com/minio/kms-go/kms v0.4.0 h1:cLPZceEp+05xHotVBaeFJrgL7JcXM4lBy6PU0idkE7I=
|
||||||
github.com/minio/kms-go/kms v0.4.0/go.mod h1:q12CehiIy2qgBnDKq6Q7wmPi2PHSyRVug5DKp0HAVeE=
|
github.com/minio/kms-go/kms v0.4.0/go.mod h1:q12CehiIy2qgBnDKq6Q7wmPi2PHSyRVug5DKp0HAVeE=
|
||||||
github.com/minio/madmin-go/v3 v3.0.57 h1:fXoOnYP8/k9x0MWWowXkAQWYu59hongieCcT3urUaAQ=
|
|
||||||
github.com/minio/madmin-go/v3 v3.0.57/go.mod h1:IFAwr0XMrdsLovxAdCcuq/eoL4nRuMVQQv0iubJANQw=
|
|
||||||
github.com/minio/madmin-go/v3 v3.0.58-0.20240701162942-671010069ecb h1:6Hx1+R0GR79Vt4gOKgadH4OG8tkrq/UNyxfmR1C7C14=
|
github.com/minio/madmin-go/v3 v3.0.58-0.20240701162942-671010069ecb h1:6Hx1+R0GR79Vt4gOKgadH4OG8tkrq/UNyxfmR1C7C14=
|
||||||
github.com/minio/madmin-go/v3 v3.0.58-0.20240701162942-671010069ecb/go.mod h1:IFAwr0XMrdsLovxAdCcuq/eoL4nRuMVQQv0iubJANQw=
|
github.com/minio/madmin-go/v3 v3.0.58-0.20240701162942-671010069ecb/go.mod h1:IFAwr0XMrdsLovxAdCcuq/eoL4nRuMVQQv0iubJANQw=
|
||||||
github.com/minio/mc v0.0.0-20240612143403-e7c9a733c680 h1:Ns5mhSm86qJx6a9GJ1kzHkZMjRMZrQGsptakVRmq4QA=
|
github.com/minio/mc v0.0.0-20240612143403-e7c9a733c680 h1:Ns5mhSm86qJx6a9GJ1kzHkZMjRMZrQGsptakVRmq4QA=
|
||||||
|
Loading…
Reference in New Issue
Block a user