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