@cryptotaxi247 / netdata-1 / commits / b0ce4f395

go.d smartctl: improve checking scsi-sat in scan (#18269)

Ilya Mashchenko committed Aug 6, 2024 at 22:40 UTC b0ce4f395850b2d2ff671a1655e038791179faab
1 file changed +40 -13
src/go/plugin/go.d/modules/smartctl/scan.go
+40 -13
@@ -5,6 +5,7 @@ package smartctl
5 import (
6 "errors"
7 "fmt"
8 + "slices"
9 "strings"
10 )
11
@@ -56,21 +57,18 @@ func (s *Smartctl) scanDevices() (map[string]*scanDevice, error) {
57 continue
58 }
59
60 + if i := slices.IndexFunc(s.ExtraDevices, func(d ConfigExtraDevice) bool { return d.Name == dev.name }); i >= 0 {
61 + s.Debugf("device %s exists in extra devices", dev.infoName)
62 + continue
63 + }
64 +
65 if !scanOpen && dev.typ == "scsi" {
66 // `smartctl --scan` attempts to guess the device type based on the path, but this can be unreliable.
67 // Accurate device type information is crucial because we use the `--device` option to gather data.
68 // Using the wrong type can lead to issues.
69 // For example, using 'scsi' for 'sat' devices prevents `smartctl` from issuing the necessary ATA commands.
64 - d := scanDevice{name: dev.name, typ: "sat"}
65 - if _, ok := s.scannedDevices[d.key()]; ok {
66 - dev.typ = "sat"
67 - } else {
68 - resp, _ := s.exec.deviceInfo(dev.name, dev.typ, s.NoCheckPowerMode)
69 - if resp != nil && isExitStatusHasBit(resp, 2) {
70 - s.Debugf("changing device '%s' type 'scsi' -> 'sat'", dev.name)
71 - dev.typ = "sat"
72 - }
73 - }
70 +
71 + s.handleGuessedScsiScannedDevice(dev)
72 }
73
74 s.Debugf("smartctl scan found device '%s' type '%s' info_name '%s'", dev.name, dev.typ, dev.infoName)
@@ -81,10 +79,8 @@ func (s *Smartctl) scanDevices() (map[string]*scanDevice, error) {
79 s.Debugf("smartctl scan found %d devices", len(devices))
80
81 for _, v := range s.ExtraDevices {
84 - if v.Name == "" || v.Type == "" {
85 - continue
86 - }
82 dev := &scanDevice{name: v.Name, typ: v.Type, extra: true}
83 +
84 if _, ok := devices[dev.key()]; !ok {
85 devices[dev.key()] = dev
86 }
@@ -96,3 +92,34 @@ func (s *Smartctl) scanDevices() (map[string]*scanDevice, error) {
92
93 return devices, nil
94 }
95 +
96 +func (s *Smartctl) handleGuessedScsiScannedDevice(dev *scanDevice) {
97 + if dev.typ != "scsi" || s.hasScannedDevice(dev) {
98 + return
99 + }
100 +
101 + d := &scanDevice{name: dev.name, typ: "sat"}
102 +
103 + if s.hasScannedDevice(d) {
104 + dev.typ = d.typ
105 + return
106 + }
107 +
108 + resp, _ := s.exec.deviceInfo(dev.name, "sat", s.NoCheckPowerMode)
109 + if resp == nil || resp.Get("smartctl.exit_status").Int() != 0 {
110 + return
111 + }
112 +
113 + atts, ok := newSmartDevice(resp).ataSmartAttributeTable()
114 + if !ok || len(atts) == 0 {
115 + return
116 + }
117 +
118 + s.Debugf("changing device '%s' type 'scsi' -> 'sat'", dev.name)
119 + dev.typ = "sat"
120 +}
121 +
122 +func (s *Smartctl) hasScannedDevice(d *scanDevice) bool {
123 + _, ok := s.scannedDevices[d.key()]
124 + return ok
125 +}