Re: [go-nuts] [HELP] How do I read SMART data from disk?
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))"
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.