storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/smart/nvme.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 * MinIO Cloud Storage, (C) 2016-2020 MinIO, Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 /* 21 * This file has been adopted and then modified from Daniel Swarbrick's smart 22 * project residing at https://github.com/dswarbrick/smart 23 * 24 */ 25 26 package smart 27 28 import ( 29 "fmt" 30 "math/big" 31 "unsafe" 32 33 "github.com/dswarbrick/smart/ioctl" 34 "golang.org/x/sys/unix" 35 ) 36 37 // NVMe admin disk query constants 38 const ( 39 NvmeAdminGetLogPage = 0x02 40 NvmeAdminIdentify = 0x06 41 ) 42 43 var ( 44 nvmeIoctlAdminCmd = ioctl.Iowr('N', 0x41, unsafe.Sizeof(nvmePassthruCommand{})) 45 ) 46 47 // NewNVMeDevice creates a new NVMeDevice struct with name 48 func NewNVMeDevice(name string) *NVMeDevice { 49 return &NVMeDevice{name, -1} 50 } 51 52 // Open - open device file to find kernel info 53 func (d *NVMeDevice) Open() (err error) { 54 d.fd, err = unix.Open(d.Name, unix.O_RDWR, 0600) 55 return err 56 } 57 58 // Close - closes device file 59 func (d *NVMeDevice) Close() error { 60 return unix.Close(d.fd) 61 } 62 63 func (d *NVMeDevice) readLogPage(logID uint8, buf *[]byte) error { 64 bufLen := len(*buf) 65 66 if (bufLen < 4) || (bufLen > 0x4000) || (bufLen%4 != 0) { 67 return fmt.Errorf("Invalid buffer size") 68 } 69 70 cmd := nvmePassthruCommand{ 71 opcode: NvmeAdminGetLogPage, 72 nsid: 0xffffffff, // FIXME 73 addr: uint64(uintptr(unsafe.Pointer(&(*buf)[0]))), 74 dataLen: uint32(bufLen), 75 cdw10: uint32(logID) | (((uint32(bufLen) / 4) - 1) << 16), 76 } 77 78 return ioctl.Ioctl(uintptr(d.fd), nvmeIoctlAdminCmd, uintptr(unsafe.Pointer(&cmd))) 79 } 80 81 // le128ToBigInt takes a little-endian 16-byte slice and returns a *big.Int representing it. 82 func le128ToBigInt(buf [16]byte) *big.Int { 83 // Int.SetBytes() expects big-endian input, so reverse the bytes locally first 84 rev := make([]byte, 16) 85 for x := 0; x < 16; x++ { 86 rev[x] = buf[16-x-1] 87 } 88 89 return new(big.Int).SetBytes(rev) 90 }