Re: [go-nuts] [HELP] How do I read SMART data from disk?

2017-05-13 Thread daniel . swarbrick
I realise this is a very old thread, but I am in the early stages of 
writing a pure Go library for reading SMART attributes from HDDs / SSDs. So 
far it works for simple SCSI block devices (i.e., those that have a sd* 
device name) via SCSI pass-through, and I am in the process of adding 
support for devices attached to MegaRAID controllers.

You can find the code at https://github.com/dswarbrick/smart

On Friday, March 23, 2012 at 12:15:16 PM UTC+1, Jeff R. Allen wrote:
>
>
>
> On Thursday, March 22, 2012 4:59:09 PM UTC+1, minux wrote:
>>
>> you can strace(1) the command line app and find out how to read these 
>> data. 
>>
>
> Out of curiosity, I did just that, and I found that smartctl is using 
> ioctl SG_IO to do SCSI Generic commands on the device:
>
> 4602  ioctl(3, SG_IO, {'S', SG_DXFER_FROM_DEV, cmd[6]=[*12, 00, 00, 00, 
> 24, 00*], mx_sb_len=32, iovec_count=0, dxfer_len=36, timeout=2, 
> flags=0, data[36]=["*\0\0\5\2[\0\0\0ATA TOSHIBA THNSNC12*"...], 
> status=00, masked_status=00, sb[0]=[], host_status=0, driver_status=0, 
> resid=0, duration=0, info=0}) = 0
>
> (The request and reply are emboldened.)
>
> You can see an example of how to access ioctl from Go in the exp/terminal 
> package: 
> http://code.google.com/p/go/source/browse/src/pkg/exp/terminal/util.go
>
> If you want to make this portable, you'll need to think about making a 
> package in Go that can do SCSI Generic commands, hiding the 
> platform-dependent parts inside of it. Take a look at the source to the net 
> package to see how to make one Go package that's got OS-dependent 
> implementations of the same external API.
>
> Then you can use your new package to talk S.M.A.R.T. with your device.
>
> I think that project would be a very good fit for Go; at the low levels, 
> you need control of the bits to do the ioctl, and once you get the data, 
> you have all the niceities of Go to transform it, store it in a database, 
> graph it, etc. Go for it!
>
>  -jeff
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[go-nuts] Working with ioctls, structs containing uintptr, and "((packed))"

2017-01-26 Thread daniel . swarbrick
Hello,

I'm trying to call Linux SCSI generic ioctls from Go, ideally without 
resorting to cgo, and have hit a few snags.

I have ported the sg_io_hdr_t struct () to Go, and according to 
http://golang-sizeof.tips, it is the same size as sizeof(sg_io_hdr_t) in C, 
and does not contain any unexpected padding or weird alignment. Using 
"unsafe", I have some working code that is able to send a SCSI INQUIRY to a 
device and get a sane response (on x64). I _assume_ that this code should 
be portable to i386 or arm64, but am open to being corrected.

Where things start to get ugly is when one has to work with packed structs, 
such as the megasas_iocpacket struct in the Linux megaraid_sas driver. This 
struct is for sending ioctls to the megaraid_sas driver, which can include 
e.g. SCSI pass-through commands for interfacing with disks attached to 
MegaRAID controllers. Porting this struct to Go and checking it on 
http://golang-sizeof.tips reveals several instances of undesired padding, 
which leads to incorrect alignment of the members when the ioctl reads them.

I do have some working code however that is able to send INQUIRY or ATA 
IDENTIFY commands, wrapped in SCSI pass-through commands, via the MegaRAID 
ioctls (aka MegaRAID Firmware Interface or MFI). I am achieving this by 
using encoding/binary to write the struct to a buffer in packed format, and 
then calling the ioctl with an unsafe pointer to that buffer. This at least 
results in the correct packing, as would be achieved in C. But it is quite 
tedious if the ioctl has to write some response into that buffer, since I 
then have to read that buffer back into the struct before I can continuing 
to work with the values written to that struct.

The impasse that I have currently reached is how to make such a packed 
struct be platform independent. Encoding/binary will not work if the struct 
contains non fixed-size members, such as int, uint or especially uintptr. 
Many ioctls pass structs that contain void* pointers to buffers which are 
expected to be written to by the ioctl. Is there a way to deal with this, 
without rewriting most of encoding/binary? I get that the size of uintptr 
is not fixed, but it can be determined at runtime or presumably compile 
time, since the target arch is known.

Will I have to resort to using cgo, and will that even deal with the packed 
struct issue? Any help or advice appreciated.

Daniel

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.