11/*
2- * Copyright 2020, 2021, 2022 Hewlett Packard Enterprise Development LP
2+ * Copyright 2020-2025 Hewlett Packard Enterprise Development LP
33 * Other additional copyright holders may be indicated within.
44 *
55 * The entirety of this work is licensed under the Apache License,
@@ -22,6 +22,7 @@ package nvme
2222import (
2323 "encoding/binary"
2424 "fmt"
25+ "math/rand"
2526 "path"
2627 "regexp"
2728 "strconv"
@@ -33,6 +34,8 @@ import (
3334 "github.com/google/uuid"
3435
3536 "github.com/NearNodeFlash/nnf-ec/internal/switchtec/pkg/switchtec"
37+ "github.com/NearNodeFlash/nnf-ec/pkg/ec"
38+ sf "github.com/NearNodeFlash/nnf-ec/pkg/rfsf/pkg/models"
3639)
3740
3841// Device describes the NVMe Device and its attributes
@@ -532,7 +535,7 @@ type id_ctrl struct {
532535 NVMSetIdentifierMaximum uint16 // NSETIDMAX
533536 EnduraceGroupIdentifierMaximum uint16 // ENDGIDMAX
534537 ANATranstitionTime uint8 // ANATT
535- AsymentricNamespaceAccessCapabilities uint8 // ANACAP
538+ AsymmetricNamespaceAccessCapabilities uint8 // ANACAP
536539 ANAGroupIdenfierMaximum uint32 // ANAGRPMAX
537540 NumberOfANAGroupIdentifiers uint32 // NANAGRPID
538541 PersistentEventLogSize uint32 // PELS
@@ -1101,7 +1104,7 @@ type SmartLog struct {
11011104 DataUnitsWrittenLo uint64
11021105 DataUnitsWrittenHi uint64
11031106 HostReadsLo uint64
1104- HistReadsHi uint64
1107+ HostReadsHi uint64
11051108 HostWritesLo uint64
11061109 HostWritesHi uint64
11071110 ControllerBusyTimeLo uint64
@@ -1126,6 +1129,7 @@ type SmartLog struct {
11261129 Reserved232 [280 ]uint8
11271130}
11281131
1132+ // GetSmartLog - retrieve the smartlog information
11291133func (dev * Device ) GetSmartLog () (* SmartLog , error ) {
11301134
11311135 log := new (SmartLog )
@@ -1146,6 +1150,53 @@ func (dev *Device) GetSmartLog() (*SmartLog, error) {
11461150 return log , nil
11471151}
11481152
1153+ // InterpretSmartLog - calculate the drive's swordfish status
1154+ func InterpretSmartLog (log * SmartLog ) sf.ResourceState {
1155+ // Check critical warnings first - check individual bitfield members
1156+ if log .CriticalWarning .SpareCapacity != 0 { // Spare capacity
1157+ return sf .DISABLED_RST
1158+ }
1159+ if log .CriticalWarning .ReadOnly != 0 { // Read-only mode
1160+ return sf .DISABLED_RST
1161+ }
1162+
1163+ // Check other critical warnings for degraded state
1164+ if log .CriticalWarning .Temperature != 0 ||
1165+ log .CriticalWarning .Degraded != 0 ||
1166+ log .CriticalWarning .BackupFailed != 0 ||
1167+ log .CriticalWarning .PersistentMemoryRegionReadOnly != 0 {
1168+ return sf .STANDBY_OFFLINE_RST
1169+ }
1170+
1171+ return sf .ENABLED_RST // Healthy
1172+ }
1173+
1174+ func MangleSmartLog (log * SmartLog ) {
1175+
1176+ // Occaionally managle the smart log data
1177+ if rand .Intn (100 ) < 10 { // 10% chance of simulating critical condition
1178+ warningType := rand .Intn (6 )
1179+ switch warningType {
1180+ case 0 :
1181+ log .CriticalWarning .SpareCapacity = 1
1182+ log .AvailableSpare = 5 // Below threshold
1183+ case 1 :
1184+ log .CriticalWarning .Temperature = 1
1185+ log .CompositeTemperature = 358 // ~85°C
1186+ case 2 :
1187+ log .CriticalWarning .Degraded = 1
1188+ case 3 :
1189+ log .CriticalWarning .ReadOnly = 1
1190+ case 4 :
1191+ log .CriticalWarning .BackupFailed = 1
1192+ case 5 :
1193+ log .CriticalWarning .PersistentMemoryRegionReadOnly = 1
1194+ }
1195+ }
1196+
1197+ }
1198+
1199+ // Log contstants
11491200const (
11501201 LogCdw10LogPageIdentiferMask = 0xFF
11511202 LogCdw10LogPageIdentiferShift = 0
@@ -1166,7 +1217,7 @@ const (
11661217)
11671218
11681219func (dev * Device ) getNsidLog (logPageIdentifier uint8 , retainAsynchronousEvent uint8 , nsid uint32 , buf []byte ) error {
1169- return dev .getLog (logPageIdentifier , 0 , 0 , nsid , 0 , buf )
1220+ return dev .getLog (logPageIdentifier , 0 , retainAsynchronousEvent , nsid , 0 , buf )
11701221}
11711222
11721223func (dev * Device ) getLog (logPageIdentifier uint8 , logSpecificField uint8 , retainAsynchronousEvent uint8 , nsid uint32 , logPageOffset uint64 , buf []byte ) error {
@@ -1200,3 +1251,26 @@ func (dev *Device) getLog(logPageIdentifier uint8, logSpecificField uint8, retai
12001251 return dev .ops .submitAdminPassthru (dev , & cmd , buf )
12011252
12021253}
1254+
1255+ // LogSmartLog outputs the SMART log data in a structured way for logging.
1256+ func LogSmartLog (log ec.Logger , smartLog * SmartLog , context ... interface {}) {
1257+ if smartLog == nil {
1258+ log .Error (nil , "SMART log is nil" , context ... )
1259+ return
1260+ }
1261+ log .Info ("SMART log data" ,
1262+ append (context ,
1263+ "criticalWarning.spareCapacity" , smartLog .CriticalWarning .SpareCapacity ,
1264+ "criticalWarning.temperature" , smartLog .CriticalWarning .Temperature ,
1265+ "criticalWarning.degraded" , smartLog .CriticalWarning .Degraded ,
1266+ "criticalWarning.readOnly" , smartLog .CriticalWarning .ReadOnly ,
1267+ "criticalWarning.backupFailed" , smartLog .CriticalWarning .BackupFailed ,
1268+ "criticalWarning.persistentMemoryRegionReadOnly" , smartLog .CriticalWarning .PersistentMemoryRegionReadOnly ,
1269+ "availableSpare" , smartLog .AvailableSpare ,
1270+ "availableSpareThreshold" , smartLog .AvailableSpareThreshold ,
1271+ "percentageUsed" , smartLog .PercentageUsed ,
1272+ "compositeTemperature" , smartLog .CompositeTemperature ,
1273+ "mediaErrorsLo" , smartLog .MediaErrorsLo ,
1274+ "numberErrorLogEntriesLo" , smartLog .NumberErrorLogEntriesLo ,
1275+ )... )
1276+ }
0 commit comments