anatol/smart.go

Compile error on Darwin: sata.go:860:20: d.readSMARTThresholds undefined

badger200 opened this issue · 5 comments

19:38:46 iPad-Pro:/src/smart.go root$ go build
# github.com/anatol/smart.go
./sata.go:860:20: d.readSMARTThresholds undefined (type *SataDevice has no field or method readSMARTThresholds, but does have ReadSMARTThresholds)

This happens when I compile on both MacOSX 10.9 and on jailbroken iOS 14.4. Both with go 1.20.

This same error occurred a year ago last time I tried.

anatol commented

Thank you for the report. It should be closed by c3b2713

@anatol Thanks I was able to run go test which PASSed, and go test examples/nvme_darwin_test.go, which failed, but it's because smartctl has never succeeded at opening the NVMe disk on my iPad, it always gets Smartctl open device: disk0 failed: IOCreatePlugInInterfaceForService failed

I am not sure where the issue lies but I'd do anything to get added to SMART data on iOS. Using ioreg tool I can see there is definitely a SMART diagnostic device with a bunch of binary data, and Apple's asptool gets advanced disk health data presumably via SMART when you install a Developer debugging Profile on your device and then collect sys logs. It actually creates a huge 300MB .tgz which I inspected and was excited to discover it reported health on my SSD NAND "bands" and there's apparently a "high endurance band" etc.

(This was on my old iPad Pro which died due to the SSD NAND failing, presumably due to excessive writing as I had been continuously building debug versions of LLVM/Clang and there was a runaway process that kept this up for almost a whole year.)

anatol commented

The error happens here

res = IOCreatePlugInInterfaceForService(disk, kIONVMeSMARTUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score);

I am looking at the failing function. Its docs say https://developer.apple.com/documentation/iokit/1412429-iocreateplugininterfaceforservic that it is available in macOS 10.0+, but it does not say anything about ios. I wonder if Apple does not provide the IOKit at iOS.

iOS definitely has IOKit, I've compiled numerous programs that succeed using it. Sometimes I have to add special entitlements for direct-disk-access, especially when trying to access hardware directly, but dmesg will always have a telltale System Policy: deny(1) direct-disk-access. And there were no Denys today.

I am pretty sure smartctl works on USB hard drives I connect to my iPad Pro USB C port. I can check later if it would help?

anatol commented

I just ran following code at my MacBook M2 and it completed successfully. It can read SMART information from the device's SSD

package main

import (
	"fmt"
	"os/exec"

	"github.com/anatol/smart.go"
)

func main() {
    path := "disk0"

	out, err := exec.Command("smartctl", "-a", path).CombinedOutput()
	fmt.Println(string(out))
	// require.NoError(t, err)  it fails at macosx because of GetLogPage()

	dev, err := smart.OpenNVMe(path)
	if err != nil {
		fmt.Println(err)
	}
	defer dev.Close()

	c, ns, err := dev.Identify()
	if err != nil {
		fmt.Println(err)
	}

        fmt.Printf("%+v\n", c)
        fmt.Printf("%+v\n", ns)
        fmt.Println(c.ModelNumber())

	sm, err := dev.ReadSMART()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%+v\n", sm)
}

It looks like the error is iOS specific.

I do not have a jailbroken iOS device to clearly tell what is going on there. I suggest you to add a few debug statements to smart.go/nvme_darwin.cpp and see what exactly the res code value is. It might give a clue what is going on there.