SG_IO v4 support ?

Bart Van Assche bart.vanassche at sandisk.com
Wed Jan 21 16:04:44 UTC 2015


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





More information about the Strace-devel mailing list