ソースを参照

Added install bus data extractor

TC 1 ヶ月 前
コミット
9cc2e98a84
4 ファイル変更140 行追加14 行削除
  1. 118 0
      mod/diskinfo/blkstat/blkstat.go
  2. 20 0
      raid.go
  3. 0 1
      web/components/disks.html
  4. 2 13
      web/components/raid.html

+ 118 - 0
mod/diskinfo/blkstat/blkstat.go

@@ -0,0 +1,118 @@
+//go:build linux
+// +build linux
+
+package blkstat
+
+/*
+	blkstat.go
+
+	This file extract the realtime disk I/O statistics from the Linux kernel
+	by reading the /sys/block/<block_name>/stat file.
+
+	Mostly you will only need to use ReadIOs, ReadSectors, WriteIOs and WriteSectors
+	to get the I/O statistics. Note that the values are accumulated since the
+	system booted, so you will need to calculate the difference between two
+	consecutive calls to get the I/O rate.
+*/
+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 // PCIe bus address of the device
+	SATAPort       string // SATA port location of the device
+	USBPort        string // USB port in {hub_id}-{port_num} format
+	NVMESlot       string // NVMe slot information
+}
+
+// GetInstalledBus retrieves the PCIe bus address, SATA port location, USB port, and NVMe slot for a given block device.
+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)
+	}
+
+	// Extract PCIe bus address, SATA port location, USB port, and NVMe slot from the resolved path
+	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] // USB port in {hub_id}-{port_num} format
+			}
+		} else if strings.HasPrefix(part, "nvme") {
+			if i+1 < len(parts) && strings.HasPrefix(parts[i+1], "nvme") {
+				nvmeSlot = parts[i+1] // NVMe slot information
+			}
+		}
+	}
+
+	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
+}
+
+// GetBlockStat retrieves the block statistics for a given block device.
+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
+}

+ 20 - 0
raid.go

@@ -1,8 +1,12 @@
 package main
 
 import (
+	"encoding/json"
 	"net/http"
 	"strings"
+
+	"imuslab.com/bokofs/bokofsd/mod/diskinfo/blkstat"
+	"imuslab.com/bokofs/bokofsd/mod/utils"
 )
 
 /*
@@ -36,6 +40,22 @@ func HandleRAIDCalls() http.Handler {
 			// Activate a RAID device, require "dev=md0" as a query parameter
 			raidManager.HandleSyncPendingToReadWrite(w, r)
 			return
+		case "test":
+			devname, err := utils.GetPara(r, "dev")
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusBadRequest)
+				return
+			}
+
+			bs, err := blkstat.GetInstalledBus(devname)
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+
+			js, _ := json.Marshal(bs)
+			utils.SendJSONResponse(w, string(js))
+			return
 		default:
 			http.Error(w, "Not Found", http.StatusNotFound)
 			return

+ 0 - 1
web/components/disks.html

@@ -151,7 +151,6 @@
             devpath = devpath.substring(5);
         }
         hostDiskInfo.disks.forEach(function(disk) {
-            console.log(disk.name, devpath);
             if (disk.name == devpath) {
                 return disk;
             }

+ 2 - 13
web/components/raid.html

@@ -110,6 +110,7 @@
                msgbox(i18nc("raid_device_updated_succ"));
             }
             $(`.raid-details[mdx=${devname}]`).show();
+            getRAIDSpaceInfoForDev(devname);
         });
 
     }
@@ -350,19 +351,7 @@
                                         </div>
                                     </div>
                                 </div>
-                                <div class="column">
-                                    <div class="ts-wrap is-middle-aligned">
-                                        <div class="ts-gauge is-small is-circular">
-                                            <div class="bar" style="--value: 100">
-                                                <div class="text">---</div>
-                                            </div>
-                                        </div>
-                                        <div>
-                                            <div class="ts-text is-bold">傳輸</div>
-                                            0 B 已使用
-                                        </div>
-                                    </div>
-                                </div>
+                                
                             </div>
 
                         </div>