Repository: minio/minio (language: go)

Issue:
MinIO crashed after metrics access
## NOTE

<!--- Provide a general summary of the issue in the Title above -->


Minio crashed when detect some drives are swapped. Panic occurred after 1-2 minutes after start instance

```
Detected unexpected drive ordering refusing to use the drive - poolID: 1st, found drive mounted at ...
...
Detected unexpected drive ordering refusing to use the drive: ...
...
panic: runtime error: index out of range [-1]

goroutine 11668 [running]:
github.com/minio/minio/cmd.GetTotalUsableCapacity(...)
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/notification-summary.go:36
github.com/minio/minio/cmd.getClusterStorageMetrics.func1({0x5173fe0, 0xc0001deec0})
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:2015 +0xeb0
github.com/minio/minio/cmd.(*MetricsGroup).RegisterRead.func1.1()
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:253 +0x2b
github.com/minio/minio/cmd.(*timedValue).Get(0xc0012bf7a0)
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/utils.go:1056 +0x48
github.com/minio/minio/cmd.(*MetricsGroup).Get(0x28fb9c3?)
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:283 +0x30
github.com/minio/minio/cmd.populateAndPublish({0xc001289720, 0x13, 0x166c080?}, 0xc01c69ffa8)
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:2255 +0x66
github.com/minio/minio/cmd.ReportMetrics.func1()
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:2220 +0x98
created by github.com/minio/minio/cmd.ReportMetrics
        /root/work/bigtop/build/minio/rpm/BUILD/minio-20221111034420/cmd/metrics-v2.go:2218 +0xeb
```

Possibly GetTotalUsableCapacity should ignore unrecognized drives

## Expected Behavior

should work

## Current Behavior

instance crashed

## Possible Solution

Ignore not assigned drives

## Steps to Reproduce (for bugs)

Swap two drives and restart minio

## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Version used (`minio --version`): from master
Latest Version: minio/minio:RELEASE.2023-01-25T00-19-54Z

minio version DEVELOPMENT.GOGET (commit-id=DEVELOPMENT.GOGET)
Runtime: go1.18.8 linux/amd64
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Copyright: 2015-0000 MinIO, Inc.

* Server setup and configuration:
* Operating System and version (`uname -a`): centos7



Discussion / hints:

Fix patch:
diff --git a/cmd/erasure-server-pool-rebalance.go b/cmd/erasure-server-pool-rebalance.go
index c23c10d835bc7..059c5b99a57d3 100644
--- a/cmd/erasure-server-pool-rebalance.go
+++ b/cmd/erasure-server-pool-rebalance.go
@@ -133,6 +133,11 @@ func (z *erasureServerPools) initRebalanceMeta(ctx context.Context, buckets []st
 	}, len(z.serverPools))
 	var totalCap, totalFree uint64
 	for _, disk := range si.Disks {
+		// Ignore invalid.
+		if disk.PoolIndex < 0 || len(diskStats) <= disk.PoolIndex {
+			// https://github.com/minio/minio/issues/16500
+			continue
+		}
 		totalCap += disk.TotalSpace
 		totalFree += disk.AvailableSpace
 
diff --git a/cmd/notification-summary.go b/cmd/notification-summary.go
index ff3933a208c90..53725f5a09099 100644
--- a/cmd/notification-summary.go
+++ b/cmd/notification-summary.go
@@ -32,6 +32,11 @@ func GetTotalCapacity(diskInfo []madmin.Disk) (capacity uint64) {
 // GetTotalUsableCapacity gets the total usable capacity in the cluster.
 func GetTotalUsableCapacity(diskInfo []madmin.Disk, s StorageInfo) (capacity uint64) {
 	for _, disk := range diskInfo {
+		// Ignore invalid.
+		if disk.PoolIndex < 0 || len(s.Backend.StandardSCData) <= disk.PoolIndex {
+			// https://github.com/minio/minio/issues/16500
+			continue
+		}
 		// Ignore parity disks
 		if disk.DiskIndex < s.Backend.StandardSCData[disk.PoolIndex] {
 			capacity += disk.TotalSpace
@@ -51,6 +56,11 @@ func GetTotalCapacityFree(diskInfo []madmin.Disk) (capacity uint64) {
 // GetTotalUsableCapacityFree gets the total usable capacity free in the cluster.
 func GetTotalUsableCapacityFree(diskInfo []madmin.Disk, s StorageInfo) (capacity uint64) {
 	for _, disk := range diskInfo {
+		// Ignore invalid.
+		if disk.PoolIndex < 0 || len(s.Backend.StandardSCData) <= disk.PoolIndex {
+			// https://github.com/minio/minio/issues/16500
+			continue
+		}
 		// Ignore parity disks
 		if disk.DiskIndex < s.Backend.StandardSCData[disk.PoolIndex] {
 			capacity += disk.AvailableSpace
diff --git a/cmd/rebalance-admin.go b/cmd/rebalance-admin.go
index d1f2317c5be43..ff92e8cbea400 100644
--- a/cmd/rebalance-admin.go
+++ b/cmd/rebalance-admin.go
@@ -61,6 +61,11 @@ func rebalanceStatus(ctx context.Context, z *erasureServerPools) (r rebalanceAdm
 		TotalSpace     uint64
 	}, len(z.serverPools))
 	for _, disk := range si.Disks {
+		// Ignore invalid.
+		if disk.PoolIndex < 0 || len(diskStats) <= disk.PoolIndex {
+			// https://github.com/minio/minio/issues/16500
+			continue
+		}
 		diskStats[disk.PoolIndex].AvailableSpace += disk.AvailableSpace
 		diskStats[disk.PoolIndex].TotalSpace += disk.TotalSpace
 	}


Test patch: