mirror of
https://github.com/pgsty/minio.git
synced 2026-07-21 13:10:22 +03:00
rename all remaining packages to internal/ (#12418)
This is to ensure that there are no projects that try to import `minio/minio/pkg` into their own repo. Any such common packages should go to `https://github.com/minio/pkg`
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
// +build linux
|
||||
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package smart
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/dswarbrick/smart/drivedb"
|
||||
"github.com/dswarbrick/smart/ioctl"
|
||||
"github.com/dswarbrick/smart/scsi"
|
||||
"github.com/dswarbrick/smart/utils"
|
||||
"github.com/minio/madmin-go"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// GetInfo - gets info about device
|
||||
func GetInfo(device string) (madmin.SmartInfo, error) {
|
||||
info := madmin.SmartInfo{
|
||||
Device: device,
|
||||
}
|
||||
|
||||
var db drivedb.DriveDb
|
||||
dec := yaml.NewDecoder(bytes.NewBuffer(MustAsset("drivedb.yaml")))
|
||||
|
||||
err := dec.Decode(&db)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
for i, d := range db.Drives {
|
||||
db.Drives[i].CompiledRegexp, _ = regexp.Compile(d.ModelRegex)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(device, "/dev/nvme") {
|
||||
d := NewNVMeDevice(device)
|
||||
if err := d.Open(); err != nil {
|
||||
return info, err
|
||||
}
|
||||
nvmeInfo, err := getNvmeInfo(d)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
info.Nvme = nvmeInfo
|
||||
return info, nil
|
||||
}
|
||||
|
||||
d, err := scsi.OpenSCSIAutodetect(device)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
switch dev := d.(type) {
|
||||
case *scsi.SCSIDevice:
|
||||
scsiInfo, err := getScsiInfo(dev)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
info.Scsi = scsiInfo
|
||||
case *scsi.SATDevice:
|
||||
ataInfo, err := getAtaInfo(dev)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
info.Ata = ataInfo
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func getNvmeInfo(d *NVMeDevice) (*madmin.SmartNvmeInfo, error) {
|
||||
buf := make([]byte, 4096)
|
||||
nvmeInfo := &madmin.SmartNvmeInfo{}
|
||||
|
||||
cmd := nvmePassthruCommand{
|
||||
opcode: NvmeAdminIdentify,
|
||||
nsid: 0, // Namespace 0, since we are identifying the controller
|
||||
addr: uint64(uintptr(unsafe.Pointer(&buf[0]))),
|
||||
dataLen: uint32(len(buf)),
|
||||
cdw10: 1, // Identify controller
|
||||
}
|
||||
|
||||
if err := ioctl.Ioctl(uintptr(d.fd), nvmeIoctlAdminCmd, uintptr(unsafe.Pointer(&cmd))); err != nil {
|
||||
return nvmeInfo, err
|
||||
}
|
||||
|
||||
var controller nvmeIdentController
|
||||
binary.Read(bytes.NewBuffer(buf[:]), utils.NativeEndian, &controller)
|
||||
|
||||
nvmeInfo.VendorID = strings.TrimSpace(fmt.Sprintf("%#04x", controller.VendorID))
|
||||
nvmeInfo.ModelNum = strings.TrimSpace(fmt.Sprintf("%s", controller.ModelNumber))
|
||||
nvmeInfo.SerialNum = strings.TrimSpace(fmt.Sprintf("%s", controller.SerialNumber))
|
||||
nvmeInfo.FirmwareVersion = strings.TrimSpace(fmt.Sprintf("%s", controller.Firmware))
|
||||
nvmeInfo.MaxDataTransferPages = 1 << controller.Mdts
|
||||
|
||||
buf2 := make([]byte, 512)
|
||||
|
||||
// Read SMART log
|
||||
if err := d.readLogPage(0x02, &buf2); err != nil {
|
||||
return nvmeInfo, err
|
||||
}
|
||||
|
||||
var sl nvmeSMARTLog
|
||||
binary.Read(bytes.NewBuffer(buf2[:]), utils.NativeEndian, &sl)
|
||||
|
||||
unitsRead := le128ToBigInt(sl.DataUnitsRead)
|
||||
unitsWritten := le128ToBigInt(sl.DataUnitsWritten)
|
||||
|
||||
nvmeInfo.CriticalWarning = fmt.Sprintf("%x", sl.CritWarning)
|
||||
nvmeInfo.Temperature = fmt.Sprintf("%d Celsius",
|
||||
((uint16(sl.Temperature[1])<<8)|uint16(sl.Temperature[0]))-273) // Kelvin to degrees Celsius
|
||||
nvmeInfo.SpareAvailable = fmt.Sprintf("%d%%", sl.AvailSpare)
|
||||
nvmeInfo.SpareThreshold = fmt.Sprintf("%d%%", sl.SpareThresh)
|
||||
nvmeInfo.DataUnitsReadBytes = unitsRead
|
||||
nvmeInfo.DataUnitsWrittenBytes = unitsWritten
|
||||
nvmeInfo.HostReadCommands = le128ToBigInt(sl.HostReads)
|
||||
nvmeInfo.HostWriteCommands = le128ToBigInt(sl.HostWrites)
|
||||
nvmeInfo.ControllerBusyTime = le128ToBigInt(sl.CtrlBusyTime)
|
||||
nvmeInfo.PowerCycles = le128ToBigInt(sl.PowerCycles)
|
||||
nvmeInfo.PowerOnHours = le128ToBigInt(sl.PowerOnHours)
|
||||
nvmeInfo.UnsafeShutdowns = le128ToBigInt(sl.UnsafeShutdowns)
|
||||
nvmeInfo.MediaAndDataIntegrityErrors = le128ToBigInt(sl.MediaErrors)
|
||||
|
||||
return nvmeInfo, nil
|
||||
}
|
||||
|
||||
func getScsiInfo(d *scsi.SCSIDevice) (*madmin.SmartScsiInfo, error) {
|
||||
return &madmin.SmartScsiInfo{}, nil
|
||||
}
|
||||
|
||||
func getAtaInfo(d *scsi.SATDevice) (*madmin.SmartAtaInfo, error) {
|
||||
return &madmin.SmartAtaInfo{}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user