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 (<scsi/sg.h>) 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.

Reply via email to