Hello,

If anyone would like to add SG_IO v4 support in strace, the (very
lightly tested) patch below could be used as a starting point. Please
note that I'm not familiar with the strace code base.

Best regards,

Bart.

[PATCH] scsi: Add bsg support

The Linux kernel supports two different versions of the SG_IO API,
namely v3 and v4. This patch adds support for version 4 of this API.
At least the sg3_utils package supports version 4 of this API. Version
4 of this API is used if /dev/bsg/H:C:I:L is used as device name.
---
 scsi.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 105 insertions(+), 7 deletions(-)

diff --git a/scsi.c b/scsi.c
index daf7252..cbc8d7a 100644
--- a/scsi.c
+++ b/scsi.c
@@ -32,6 +32,7 @@
 
 # include <sys/ioctl.h>
 # include <scsi/sg.h>
+# include <linux/bsg.h>
 
 #include "xlat/sg_io_dxfer_direction.h"
 
@@ -59,9 +60,8 @@ print_sg_io_buffer(struct tcb *tcp, unsigned char *addr, 
const unsigned int len)
 }
 
 static void
-print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
+print_sg_io_v3_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
 {
-       tprintf("{'%c', ", sg_io->interface_id);
        printxval(sg_io_dxfer_direction, sg_io->dxfer_direction,
                  "SG_DXFER_???");
        tprintf(", cmd[%u]=[", sg_io->cmd_len);
@@ -82,7 +82,7 @@ print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
 }
 
 static void
-print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
+print_sg_io_v3_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
 {
        if (sg_io->dxfer_direction == SG_DXFER_FROM_DEV ||
            sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
@@ -102,26 +102,124 @@ print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
        tprintf("info=%#x}", sg_io->info);
 }
 
+static void
+print_sg_io_v4_req(struct tcb *tcp, struct sg_io_v4 *sg_io)
+{
+       static const struct xlat sgv4_prot[] = {
+               { BSG_PROTOCOL_SCSI, "BSG_PROTOCOL_SCSI" },
+       };
+       static const struct xlat sgv4_subpr[] = {
+               { BSG_SUB_PROTOCOL_SCSI_CMD, "BSG_SUB_PROTOCOL_SCSI_CMD" },
+               { BSG_SUB_PROTOCOL_SCSI_TMF, "BSG_SUB_PROTOCOL_SCSI_TMF" },
+               { BSG_SUB_PROTOCOL_SCSI_TRANSPORT,
+                 "BSG_SUB_PROTOCOL_SCSI_TRANSPORT" },
+       };
+
+       printxval(sgv4_prot, sg_io->protocol, "BSG_PROTOCOL_???");
+       tprints(", ");
+       printxval(sgv4_subpr, sg_io->subprotocol, "BSG_SUB_PROTOCOL_???");
+       tprintf(", request[%u]=[", sg_io->request_len);
+       printstr(tcp, sg_io->request, sg_io->request_len);
+       tprints("]");
+       tprintf(", request_tag=%llu", sg_io->request_tag);
+       tprintf(", request_attr=%u", sg_io->request_attr);
+       tprintf(", request_priority=%u", sg_io->request_priority);
+       tprintf(", request_extra=%u", sg_io->request_extra);
+
+       tprintf(", dout_iovec_count=%u", sg_io->dout_iovec_count);
+       tprintf(", dout_xfer_len=%u", sg_io->dout_xfer_len);
+       tprintf(", din_iovec_count=%u", sg_io->din_iovec_count);
+       tprintf(", din_xfer_len=%u", sg_io->din_xfer_len);
+       tprintf(", timeout=%u ms", sg_io->timeout);
+       tprintf(", flags=%u", sg_io->flags);
+       tprintf(", usr_ptr=%llu", sg_io->usr_ptr);
+       tprintf(", spare_in=%u", sg_io->spare_in);
+       if (1) {
+               tprintf(", din[%u]=[", sg_io->din_xfer_len);
+               printstr(tcp, sg_io->din_xferp, sg_io->din_xfer_len);
+               tprints("]");
+       }
+}
+
+static void
+print_sg_io_v4_res(struct tcb *tcp, struct sg_io_v4 *sg_io)
+{
+       if (1) {
+               tprintf(", response[%u]=[", sg_io->response_len);
+               printstr(tcp, sg_io->response, sg_io->response_len);
+               tprints("]");
+       }
+       if (1) {
+               tprintf(", dout[%u]=[", sg_io->dout_xfer_len);
+               printstr(tcp, sg_io->dout_xferp, sg_io->dout_xfer_len);
+               tprints("]");
+       }
+       tprintf(", driver_status=%u", sg_io->driver_status);
+       tprintf(", transport_status=%u", sg_io->transport_status);
+       tprintf(", device_status=%u", sg_io->device_status);
+       tprintf(", retry_delay=%u", sg_io->retry_delay);
+       tprintf(", info=%u", sg_io->info);
+       tprintf(", duration=%u", sg_io->duration);
+       tprintf(", response_len=%u", sg_io->response_len);
+       tprintf(", din_resid=%u", sg_io->din_resid);
+       tprintf(", dout_resid=%u", sg_io->dout_resid);
+       tprintf(", generated_tag=%llu", sg_io->generated_tag);
+       tprintf(", spare_out=%u}", sg_io->spare_out);
+}
+
+static void
+print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
+{
+       tprintf("{'%c', ", sg_io->interface_id);
+       switch (sg_io->interface_id) {
+       case 'S':
+               print_sg_io_v3_req(tcp, sg_io);
+               break;
+       case 'Q':
+               print_sg_io_v4_req(tcp, (void *)sg_io);
+               break;
+       }
+}
+
+static void
+print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
+{
+       switch (sg_io->interface_id) {
+       case 'S':
+               print_sg_io_v3_res(tcp, sg_io);
+               break;
+       case 'Q':
+               print_sg_io_v4_res(tcp, (void *)sg_io);
+               break;
+       }
+}
+
 int
 scsi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
        switch (code) {
        case SG_IO:
                if (entering(tcp)) {
-                       struct sg_io_hdr sg_io;
+                       union {
+                               struct sg_io_hdr sg_io_v3;
+                               struct sg_io_v4  sg_io_v4;
+                       } sg_io;
 
                        if (umove(tcp, arg, &sg_io) < 0)
                                tprintf(", %#lx", arg);
                        else {
                                tprints(", ");
-                               print_sg_io_req(tcp, &sg_io);
+                               print_sg_io_req(tcp, &sg_io.sg_io_v3);
                        }
                }
                if (exiting(tcp)) {
-                       struct sg_io_hdr sg_io;
+                       union {
+                               struct sg_io_hdr sg_io_v3;
+                               struct sg_io_v4  sg_io_v4;
+                       } sg_io;
 
                        if (!syserror(tcp) && umove(tcp, arg, &sg_io) >= 0)
-                               print_sg_io_res(tcp, &sg_io);
+                               print_sg_io_res(tcp, &sg_io.sg_io_v3);
                        else
                                tprints("}");
                }
-- 
2.1.2


------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to