From b9269151a4376c64f7c099a9d18cdec391867f1a Mon Sep 17 00:00:00 2001 From: Anis Eleuch Date: Wed, 6 Sep 2023 20:37:57 +0100 Subject: [PATCH] fix: drive rotational calculation status for partitions (#17986) Fix drive rotational calculation status If a MinIO drive path is mounted to a partition and not a real disk, getting the rotational status would fail because Linux does not expose that status to partition; In other words, /sys/block/drive-partition-name/queue/rotational does not exist; To fix the issue, the code will search for the rotational status of the disk that hosts the partition, and this can be calculated from the real path of /sys/class/block/ --- internal/disk/stat_linux.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/internal/disk/stat_linux.go b/internal/disk/stat_linux.go index 0bf1e0d44..ce08ea940 100644 --- a/internal/disk/stat_linux.go +++ b/internal/disk/stat_linux.go @@ -24,6 +24,7 @@ import ( "bufio" "fmt" "os" + "path/filepath" "strconv" "strings" "syscall" @@ -71,23 +72,36 @@ func GetInfo(path string, firstTime bool) (info Info, err error) { if firstTime { bfs, err := blockdevice.NewDefaultFS() if err == nil { + devName := "" diskstats, _ := bfs.ProcDiskstats() for _, dstat := range diskstats { // ignore all loop devices if strings.HasPrefix(dstat.DeviceName, "loop") { continue } - qst, err := bfs.SysBlockDeviceQueueStats(dstat.DeviceName) - if err != nil { - continue - } - rot := qst.Rotational == 1 // Rotational is '1' if the device is HDD if dstat.MajorNumber == info.Major && dstat.MinorNumber == info.Minor { - info.Name = dstat.DeviceName - info.Rotational = &rot + devName = dstat.DeviceName break } } + if devName != "" { + info.Name = devName + qst, err := bfs.SysBlockDeviceQueueStats(devName) + if err != nil { // Mostly not found error + // Check if there is a parent device: + // e.g. if the mount is based on /dev/nvme0n1p1, let's calculate the + // real device name (nvme0n1) to get its sysfs information + parentDevPath, e := os.Readlink("/sys/class/block/" + devName) + if e == nil { + parentDev := filepath.Base(filepath.Dir(parentDevPath)) + qst, err = bfs.SysBlockDeviceQueueStats(parentDev) + } + } + if err == nil { + rot := qst.Rotational == 1 // Rotational is '1' if the device is HDD + info.Rotational = &rot + } + } } }