123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package blkstat
- import (
- "fmt"
- "os"
- "strconv"
- "strings"
- )
- type BlockStat struct {
- ReadIOs uint64
- ReadMerges uint64
- ReadSectors uint64
- ReadTicks uint64
- WriteIOs uint64
- WriteMerges uint64
- WriteSectors uint64
- WriteTicks uint64
- InFlight uint64
- IoTicks uint64
- TimeInQueue uint64
- }
- type InstallPosition struct {
- PCIEBusAddress string
- SATAPort string
- USBPort string
- NVMESlot string
- }
- func GetInstalledBus(blockName string) (*InstallPosition, error) {
- linkPath := fmt.Sprintf("/sys/block/%s", blockName)
- realPath, err := os.Readlink(linkPath)
- if err != nil {
- return nil, fmt.Errorf("failed to read symlink for block device: %w", err)
- }
-
- parts := strings.Split(realPath, "/")
- var pcieBusAddress, sataPort, usbPort, nvmeSlot string
- for i, part := range parts {
- if strings.HasPrefix(part, "pci") {
- pcieBusAddress = part
- } else if strings.HasPrefix(part, "ata") {
- sataPort = part
- } else if strings.HasPrefix(part, "usb") {
- if i+1 < len(parts) && strings.Contains(parts[i+1], ":") {
- usbPort = parts[i]
- }
- } else if strings.HasPrefix(part, "nvme") {
- if i+1 < len(parts) && strings.HasPrefix(parts[i+1], "nvme") {
- nvmeSlot = parts[i+1]
- }
- }
- }
- if pcieBusAddress == "" && sataPort == "" && usbPort == "" && nvmeSlot == "" {
- return nil, fmt.Errorf("failed to extract PCIe bus address, SATA port, USB port, or NVMe slot")
- }
- return &InstallPosition{
- PCIEBusAddress: pcieBusAddress,
- SATAPort: sataPort,
- USBPort: usbPort,
- NVMESlot: nvmeSlot,
- }, nil
- }
- func GetBlockStat(blockName string) (*BlockStat, error) {
- statPath := fmt.Sprintf("/sys/block/%s/stat", blockName)
- data, err := os.ReadFile(statPath)
- if err != nil {
- return nil, fmt.Errorf("failed to read stat file: %w", err)
- }
- fields := strings.Fields(string(data))
- if len(fields) < 11 {
- return nil, fmt.Errorf("unexpected stat file format")
- }
- values := make([]uint64, 11)
- for i := 0; i < 11; i++ {
- values[i], err = strconv.ParseUint(fields[i], 10, 64)
- if err != nil {
- return nil, fmt.Errorf("failed to parse stat value: %w", err)
- }
- }
- return &BlockStat{
- ReadIOs: values[0],
- ReadMerges: values[1],
- ReadSectors: values[2],
- ReadTicks: values[3],
- WriteIOs: values[4],
- WriteMerges: values[5],
- WriteSectors: values[6],
- WriteTicks: values[7],
- InFlight: values[8],
- IoTicks: values[9],
- TimeInQueue: values[10],
- }, nil
- }
|