@@ -283,48 +283,40 @@ func convertHistogram(hist Histogram) (uint64, map[float64]uint64) {
283283
284284// getNVMEMetrics retrieves NVMe metrics by reading the log page from the NVMe device at the given path.
285285func getNVMEMetrics (devicePath string ) ([]byte , error ) {
286- f , err := os .OpenFile (devicePath , os .O_RDWR , 0 )
287- if err != nil {
288- return nil , fmt .Errorf ("getNVMEMetrics: error opening device: %w" , err )
289- }
290- defer func () {
291- if err := f .Close (); err != nil {
292- klog .ErrorS (err , "Failed to close device file" , "devicePath" , devicePath )
293- }
294- }()
295-
296- data , err := nvmeReadLogPage (f .Fd (), 0xD0 )
297- if err != nil {
298- return nil , fmt .Errorf ("getNVMEMetrics: error reading log page %w" , err )
299- }
300-
301- return data , nil
302- }
303-
304- // nvmeReadLogPage reads an NVMe log page via an ioctl system call.
305- func nvmeReadLogPage (fd uintptr , logID uint8 ) ([]byte , error ) {
306- data := make ([]byte , 4096 ) // 4096 bytes is the length of the log page.
307- bufferLen := len (data )
308-
309- if bufferLen > math .MaxUint32 {
310- return nil , errors .New ("nvmeReadLogPage: bufferLen exceeds MaxUint32" )
286+ bufferLen := binary .Size (EBSMetrics {})
287+ if bufferLen > math .MaxUint32 || bufferLen <= 0 {
288+ return nil , fmt .Errorf ("getNVMEMetrics: invalid buffer size: %d" , bufferLen )
311289 }
312290
291+ // Allocate before opening the device so we hold it open for as little time as possible
292+ data := make ([]byte , bufferLen )
313293 cmd := nvmePassthruCommand {
314294 opcode : 0x02 ,
315295 addr : uint64 (uintptr (unsafe .Pointer (& data [0 ]))),
316296 nsid : 1 ,
317297 dataLen : uint32 (bufferLen ),
318- cdw10 : uint32 ( logID ) | (1024 << 16 ),
298+ cdw10 : 0xD0 | (1024 << 16 ),
319299 }
320300
321- status , _ , errno := unix .Syscall (unix .SYS_IOCTL , fd , 0xC0484E41 , uintptr (unsafe .Pointer (& cmd )))
301+ // Write handle is not needed to call ioctl on linux, thus open RDONLY
302+ f , err := os .OpenFile (devicePath , os .O_RDONLY , 0 )
303+ if err != nil {
304+ return nil , fmt .Errorf ("getNVMEMetrics: error opening device: %w" , err )
305+ }
306+ defer func () {
307+ if err := f .Close (); err != nil {
308+ klog .ErrorS (err , "Failed to close device file" , "devicePath" , devicePath )
309+ }
310+ }()
311+
312+ status , _ , errno := unix .Syscall (unix .SYS_IOCTL , f .Fd (), 0xC0484E41 , uintptr (unsafe .Pointer (& cmd )))
322313 if errno != 0 {
323- return nil , fmt .Errorf ("nvmeReadLogPage : ioctl error %w" , errno )
314+ return nil , fmt .Errorf ("getNVMEMetrics : ioctl error %w" , errno )
324315 }
325316 if status != 0 {
326- return nil , fmt .Errorf ("nvmeReadLogPage : ioctl command failed with status %d" , status )
317+ return nil , fmt .Errorf ("getNVMEMetrics : ioctl command failed with status %d" , status )
327318 }
319+
328320 return data , nil
329321}
330322
0 commit comments