1// Copyright 2021 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14// +build linux 15 16package sysfs 17 18import ( 19 "fmt" 20 "io/ioutil" 21 "path/filepath" 22 23 "github.com/prometheus/procfs/internal/util" 24) 25 26const nvmeClassPath = "class/nvme" 27 28// NVMeDevice contains info from files in /sys/class/nvme for a single NVMe device. 29type NVMeDevice struct { 30 Name string 31 Serial string // /sys/class/nvme/<Name>/serial 32 Model string // /sys/class/nvme/<Name>/model 33 State string // /sys/class/nvme/<Name>/state 34 FirmwareRevision string // /sys/class/nvme/<Name>/firmware_rev 35} 36 37// NVMeClass is a collection of every NVMe device in /sys/class/nvme. 38// 39// The map keys are the names of the NVMe devices. 40type NVMeClass map[string]NVMeDevice 41 42// NVMeClass returns info for all NVMe devices read from /sys/class/nvme. 43func (fs FS) NVMeClass() (NVMeClass, error) { 44 path := fs.sys.Path(nvmeClassPath) 45 46 dirs, err := ioutil.ReadDir(path) 47 if err != nil { 48 return nil, fmt.Errorf("failed to list NVMe devices at %q: %w", path, err) 49 } 50 51 nc := make(NVMeClass, len(dirs)) 52 for _, d := range dirs { 53 device, err := fs.parseNVMeDevice(d.Name()) 54 if err != nil { 55 return nil, err 56 } 57 58 nc[device.Name] = *device 59 } 60 61 return nc, nil 62} 63 64// Parse one NVMe device. 65func (fs FS) parseNVMeDevice(name string) (*NVMeDevice, error) { 66 path := fs.sys.Path(nvmeClassPath, name) 67 device := NVMeDevice{Name: name} 68 69 for _, f := range [...]string{"firmware_rev", "model", "serial", "state"} { 70 name := filepath.Join(path, f) 71 value, err := util.SysReadFile(name) 72 if err != nil { 73 return nil, fmt.Errorf("failed to read file %q: %w", name, err) 74 } 75 76 switch f { 77 case "firmware_rev": 78 device.FirmwareRevision = value 79 case "model": 80 device.Model = value 81 case "serial": 82 device.Serial = value 83 case "state": 84 device.State = value 85 } 86 } 87 88 return &device, nil 89} 90