Skip to content

Commit

Permalink
chore(sysfs,probe): backport sysfs probe to v0.4.x (#395)
Browse files Browse the repository at this point in the history
- add sysfs probe
- remove capacity probe
- add logical block size, physical block size, hardware sector size and drive type
- use smartprobe to fill in capacity only if sysfs probe fails to fetch capacity

Signed-off-by: Akhil Mohan <akhil.mohan@mayadata.io>
  • Loading branch information
akhilerm committed Mar 24, 2020
1 parent a00c2bb commit 7fa8ca0
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 140 deletions.
16 changes: 11 additions & 5 deletions cmd/ndm_daemonset/controller/blockdevice.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ type DeviceInfo struct {
ByIdDevLinks []string // ByIdDevLinks contains by-id devlinks
ByPathDevLinks []string // ByPathDevLinks contains by-path devlinks
FirmwareRevision string // FirmwareRevision is the firmware revision for a disk
LogicalSectorSize uint32 // LogicalSectorSize is the Logical size of blockdevice sector in bytes
PhysicalSectorSize uint32 // PhysicalSectorSize is the Physical size of blockdevice sector in bytes
LogicalBlockSize uint32 // LogicalBlockSize is the Logical size of disk block in bytes
PhysicalBlockSize uint32 // PhysicalBlockSize is the Physical size of disk block in bytes
HardwareSectorSize uint32 //HardwareSector size in bytes
Compliance string // Compliance is implemented specifications version i.e. SPC-1, SPC-2, etc
DeviceType string // DeviceType represents the type of backing disk
DeviceType string // DeviceType represents the type of device, sparse/partition/lvm
DriveType string // DriveType represents the type of backing disk HDD/SSD
PartitionType string // Partition type if the blockdevice is a partition
FileSystemInfo FSInfo // FileSystem info of the blockdevice like FSType and MountPoint
}
Expand Down Expand Up @@ -129,6 +131,10 @@ func (di *DeviceInfo) getPath() string {
// It is used to populate data of BlockDevice struct which of BlockDevice CR.
func (di *DeviceInfo) getDeviceDetails() apis.DeviceDetails {
deviceDetails := apis.DeviceDetails{}
deviceDetails.LogicalBlockSize = di.LogicalBlockSize
deviceDetails.PhysicalBlockSize = di.PhysicalBlockSize
deviceDetails.HardwareSectorSize = di.HardwareSectorSize
deviceDetails.DriveType = di.DriveType
deviceDetails.Model = di.Model
deviceDetails.Serial = di.Serial
deviceDetails.Vendor = di.Vendor
Expand All @@ -146,8 +152,8 @@ func (di *DeviceInfo) getDeviceDetails() apis.DeviceDetails {
func (di *DeviceInfo) getDeviceCapacity() apis.DeviceCapacity {
capacity := apis.DeviceCapacity{}
capacity.Storage = di.Capacity
capacity.LogicalSectorSize = di.LogicalSectorSize
capacity.PhysicalSectorSize = di.PhysicalSectorSize
capacity.LogicalSectorSize = di.LogicalBlockSize
capacity.PhysicalSectorSize = di.PhysicalBlockSize
return capacity
}

Expand Down
5 changes: 3 additions & 2 deletions cmd/ndm_daemonset/controller/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ type DiskInfo struct {
ByIdDevLinks []string // ByIdDevLinks contains by-id devlinks
ByPathDevLinks []string // ByPathDevLinks contains by-path devlinks
FirmwareRevision string // FirmwareRevision is the firmware revision for a disk
LogicalSectorSize uint32 // LogicalSectorSize is the Logical size of disk sector in bytes
PhysicalSectorSize uint32 // PhysicalSectorSize is the Physical size of disk sector in bytes
LogicalSectorSize uint32 // LogicalBlockSize is the Logical size of disk sector in bytes
PhysicalSectorSize uint32 // PhysicalBlockSize is the Physical size of disk sector in bytes
HardwareSectorSize uint32 // HardwareSectorSize is the sector size of disk in bytes
RotationRate uint16 // 0 = not reported. 1 = SSD, everything else is an RPM
Compliance string // Compliance is implemented specifications version i.e. SPC-1, SPC-2, etc
DiskType string // DiskType represents the type of disk like Disk, Sparse etc.,
Expand Down
8 changes: 5 additions & 3 deletions cmd/ndm_daemonset/controller/disk_to_device_convertor.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ func (c *Controller) NewDeviceInfoFromDiskInfo(diskDetails *DiskInfo) *DeviceInf
deviceDetails.Path = diskDetails.Path
deviceDetails.ByIdDevLinks = diskDetails.ByIdDevLinks
deviceDetails.ByPathDevLinks = diskDetails.ByPathDevLinks
deviceDetails.LogicalSectorSize = diskDetails.LogicalSectorSize
deviceDetails.PhysicalSectorSize = diskDetails.PhysicalSectorSize
deviceDetails.LogicalBlockSize = diskDetails.LogicalSectorSize
deviceDetails.PhysicalBlockSize = diskDetails.PhysicalSectorSize
deviceDetails.HardwareSectorSize = diskDetails.HardwareSectorSize
deviceDetails.Compliance = diskDetails.Compliance
deviceDetails.DeviceType = diskDetails.DriveType
deviceDetails.DriveType = diskDetails.DriveType
deviceDetails.DeviceType = diskDetails.DiskType
deviceDetails.FileSystemInfo.FileSystem = diskDetails.FileSystemInformation.FileSystem
deviceDetails.FileSystemInfo.MountPoint = diskDetails.FileSystemInformation.MountPoint
return deviceDetails
Expand Down
109 changes: 0 additions & 109 deletions cmd/ndm_daemonset/probe/capacityprobe.go

This file was deleted.

2 changes: 1 addition & 1 deletion cmd/ndm_daemonset/probe/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var RegisteredProbes = []func(){
smartProbeRegister,
mountProbeRegister,
udevProbeRegister,
capacityProbeRegister}
sysfsProbeRegister}

type registerProbe struct {
priority int
Expand Down
6 changes: 3 additions & 3 deletions cmd/ndm_daemonset/probe/seachestprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type seachestProbe struct {

const (
seachestConfigKey = "seachest-probe"
seachestProbePriority = 2
seachestProbePriority = 4
)

var (
Expand Down Expand Up @@ -143,12 +143,12 @@ func (scp *seachestProbe) FillDiskDetails(d *controller.DiskInfo) {

if d.LogicalSectorSize == 0 {
d.LogicalSectorSize = seachestProbe.SeachestIdentifier.GetLogicalSectorSize(driveInfo)
klog.V(4).Infof("Disk: %s LogicalSectorSize:%d filled by seachest.", d.Path, d.LogicalSectorSize)
klog.V(4).Infof("Disk: %s LogicalBlockSize:%d filled by seachest.", d.Path, d.LogicalSectorSize)
}

if d.PhysicalSectorSize == 0 {
d.PhysicalSectorSize = seachestProbe.SeachestIdentifier.GetPhysicalSectorSize(driveInfo)
klog.V(4).Infof("Disk: %s PhysicalSectorSize:%d filled by seachest.", d.Path, d.PhysicalSectorSize)
klog.V(4).Infof("Disk: %s PhysicalBlockSize:%d filled by seachest.", d.Path, d.PhysicalSectorSize)
}

if d.RotationRate == 0 {
Expand Down
12 changes: 10 additions & 2 deletions cmd/ndm_daemonset/probe/smartprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,15 @@ func (sp *smartProbe) FillDiskDetails(d *controller.DiskInfo) {

d.Compliance = deviceBasicSCSIInfo.Compliance
d.FirmwareRevision = deviceBasicSCSIInfo.FirmwareRevision
d.Capacity = deviceBasicSCSIInfo.Capacity
d.LogicalSectorSize = deviceBasicSCSIInfo.LBSize
if d.Capacity == 0 {
d.Capacity = deviceBasicSCSIInfo.Capacity
klog.V(4).Infof("Disk path: %s capacity :%d filled by smart probe.",
d.Path, d.Capacity)
}
if d.LogicalSectorSize == 0 {
d.LogicalSectorSize = deviceBasicSCSIInfo.LBSize
klog.V(4).Infof("Disk path: %s logical block size :%d filled by smart probe.",
d.Path, d.LogicalSectorSize)
}

}
172 changes: 172 additions & 0 deletions cmd/ndm_daemonset/probe/sysfsprobe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
Copyright 2020 OpenEBS Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
Find queue sysfs doc here.
https://www.kernel.org/doc/Documentation/block/queue-sysfs.txt
*/

package probe

import (
"io/ioutil"
"strconv"
"strings"

"github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller"
"github.com/openebs/node-disk-manager/pkg/util"
"k8s.io/klog"
)

const (
sysfsProbePriority = 2
sysfsConfigKey = "sysfs-probe"
// sectorSize is the sector size as understood by the unix systems.
// It is kept as 512 bytes. all entries in /sys/class/block/sda/size
// are in 512 byte blocks
sectorSize int64 = 512
)

var (
sysfsProbeName = "sysfs probe"
sysfsProbeState = defaultEnabled
)

var sysfsProbeRegister = func() {
ctrl := <-controller.ControllerBroadcastChannel
if ctrl == nil {
klog.Error("unable to configure", sysfsProbeName)
return
}
if ctrl.NDMConfig != nil {
for _, probeConfig := range ctrl.NDMConfig.ProbeConfigs {
if probeConfig.Key == sysfsConfigKey {
sysfsProbeName = probeConfig.Name
sysfsProbeState = util.CheckTruthy(probeConfig.State)
break
}
}
}

newRegistryProbe := &registerProbe{
priority: sysfsProbePriority,
name: sysfsProbeName,
state: sysfsProbeState,
pi: newSysFSProbe(),
controller: ctrl,
}
newRegistryProbe.register()
}

// sysfsProbe fills the logical sector size,
// physical sector size, drive type(ssd or hdd) of the disk
type sysfsProbe struct {
}

func newSysFSProbe() *sysfsProbe {
return &sysfsProbe{}
}

// It is part of probe interface. Hence, empty implementation.
func (cp *sysfsProbe) Start() {}

// FillDiskDetails updates the logical sector size,
// physical sector size, drive type(ssd or hdd) of the disk
// if those are not populated.
func (cp *sysfsProbe) FillDiskDetails(d *controller.DiskInfo) {
sysPath := d.ProbeIdentifiers.UdevIdentifier

if d.LogicalSectorSize == 0 {
logicalBlockSize, err := readSysFSFileAsInt64(sysPath + "/queue/logical_block_size")
if err != nil {
klog.Warning("unable to read logical block size", err)
} else if logicalBlockSize != 0 {
d.LogicalSectorSize = uint32(logicalBlockSize)
klog.V(4).Infof("Disk: %s logical block size: %d filled by sysfs probe.",
d.Path, d.LogicalSectorSize)
}
}

if d.PhysicalSectorSize == 0 {
physicalBlockSize, err := readSysFSFileAsInt64(sysPath + "/queue/physical_block_size")
if err != nil {
klog.Warning("unable to read physical block size", err)
} else if physicalBlockSize != 0 {
d.PhysicalSectorSize = uint32(physicalBlockSize)
klog.V(4).Infof("Disk: %s physical block size :%d filled by sysfs probe.",
d.Path, d.PhysicalSectorSize)
}
}

if d.HardwareSectorSize == 0 {
hwSectorSize, err := readSysFSFileAsInt64(sysPath + "/queue/hw_sector_size")
if err != nil {
klog.Warning("unable to read hardware sector size", err)
} else if hwSectorSize != 0 {
d.HardwareSectorSize = uint32(hwSectorSize)
klog.V(4).Infof("Disk: %s hardware sector size :%d filled by sysfs probe.",
d.Path, d.HardwareSectorSize)
}
}

if d.DriveType == "" {
rotational, err := readSysFSFileAsInt64(sysPath + "/queue/rotational")
if err != nil {
klog.Warning("unable to read rotational value", err)
} else {
if rotational == 1 {
d.DriveType = "HDD"

} else if rotational == 0 {
d.DriveType = "SSD"
}
klog.V(4).Infof("Disk path: %s drive type :%s filled by sysfs probe.",
d.Path, d.DriveType)
}
}

if d.Capacity == 0 {
// The size (/size) entry returns the `nr_sects` field of the block device structure.
// Ref: https://elixir.bootlin.com/linux/v4.4/source/fs/block_dev.c#L1267
//
// Traditionally, in Unix disk size contexts, “sector” or “block” means 512 bytes,
// regardless of what the manufacturer of the underlying hardware might call a “sector” or “block”
// Ref: https://elixir.bootlin.com/linux/v4.4/source/fs/block_dev.c#L487
//
// Therefore, to get the capacity of the device it needs to always multiplied with 512
numberOfBlocks, err := readSysFSFileAsInt64(sysPath + "/size")
if err != nil {
klog.Warning("unable to block count", err)
return
} else if numberOfBlocks != 0 {
d.Capacity = uint64(numberOfBlocks * sectorSize)
klog.V(4).Infof("Disk path: %s capacity :%d filled by sysfs probe.",
d.Path, d.Capacity)
}
}
}

// readSysFSFileAsInt64 reads a file and
// converts that content into int64
func readSysFSFileAsInt64(sysPath string) (int64, error) {
b, err := ioutil.ReadFile(sysPath)
if err != nil {
return 0, err
}
return strconv.ParseInt(strings.TrimSuffix(string(b), "\n"), 10, 64)
}

0 comments on commit 7fa8ca0

Please sign in to comment.