]> granicus.if.org Git - strace/blob - sg_io_v4.c
maint: update for linux v5.3-rc8
[strace] / sg_io_v4.c
1 /*
2  * Copyright (c) 2015 Bart Van Assche <bart.vanassche@sandisk.com>
3  * Copyright (c) 2015-2018 Dmitry V. Levin <ldv@altlinux.org>
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  */
8
9 #include "defs.h"
10
11 #ifdef HAVE_LINUX_BSG_H
12
13 # include "print_fields.h"
14 # include <linux/bsg.h>
15 # include "xlat/bsg_protocol.h"
16 # include "xlat/bsg_subprotocol.h"
17 # include "xlat/bsg_flags.h"
18
19 static void
20 print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr,
21                    const unsigned int data_size, const unsigned int iovec_count)
22 {
23         if (iovec_count) {
24                 tprint_iov_upto(tcp, iovec_count, addr, IOV_DECODE_STR,
25                                 data_size);
26         } else {
27                 printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX);
28         }
29 }
30
31 # define PRINT_FIELD_SG_IO_BUFFER(prefix_, where_, field_, size_, count_, tcp_) \
32         do {                                                                    \
33                 STRACE_PRINTF("%s%s=", (prefix_), #field_);                     \
34                 print_sg_io_buffer((tcp_), (where_).field_, (size_), (count_)); \
35         } while (0)
36
37 static int
38 decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
39 {
40         struct sg_io_v4 sg_io;
41         static const size_t skip_iid = offsetof(struct sg_io_v4, protocol);
42
43         tprints("{guard='Q', ");
44         if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid,
45                                 &sg_io.protocol)) {
46                 tprints("}");
47                 return RVAL_IOCTL_DECODED;
48         }
49
50         PRINT_FIELD_XVAL("", sg_io, protocol, bsg_protocol, "BSG_PROTOCOL_???");
51         PRINT_FIELD_XVAL(", ", sg_io, subprotocol, bsg_subprotocol,
52                          "BSG_SUB_PROTOCOL_???");
53         PRINT_FIELD_U(", ", sg_io, request_len);
54         PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, request, sg_io.request_len,
55                                  0, tcp);
56         PRINT_FIELD_X(", ", sg_io, request_tag);
57         PRINT_FIELD_U(", ", sg_io, request_attr);
58         PRINT_FIELD_U(", ", sg_io, request_priority);
59         PRINT_FIELD_U(", ", sg_io, request_extra);
60         PRINT_FIELD_U(", ", sg_io, max_response_len);
61
62         PRINT_FIELD_U(", ", sg_io, dout_iovec_count);
63         PRINT_FIELD_U(", ", sg_io, dout_xfer_len);
64         PRINT_FIELD_U(", ", sg_io, din_iovec_count);
65         PRINT_FIELD_U(", ", sg_io, din_xfer_len);
66         PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, dout_xferp, sg_io.dout_xfer_len,
67                                  sg_io.dout_iovec_count, tcp);
68
69         PRINT_FIELD_U(", ", sg_io, timeout);
70         PRINT_FIELD_FLAGS(", ", sg_io, flags, bsg_flags, "BSG_FLAG_???");
71         PRINT_FIELD_X(", ", sg_io, usr_ptr);
72
73         struct sg_io_v4 *entering_sg_io = malloc(sizeof(*entering_sg_io));
74         if (entering_sg_io) {
75                 memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
76                 entering_sg_io->guard = (unsigned char) 'Q';
77                 set_tcb_priv_data(tcp, entering_sg_io, free);
78         }
79
80         return 0;
81 }
82
83 static int
84 decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
85 {
86         struct sg_io_v4 *entering_sg_io = get_tcb_priv_data(tcp);
87         struct sg_io_v4 sg_io;
88         uint32_t din_len;
89
90         if (umove(tcp, arg, &sg_io) < 0) {
91                 /* print i/o fields fetched on entering syscall */
92                 PRINT_FIELD_X(", ", *entering_sg_io, response);
93                 PRINT_FIELD_X(", ", *entering_sg_io, din_xferp);
94                 return RVAL_IOCTL_DECODED;
95         }
96
97         if (sg_io.guard != entering_sg_io->guard) {
98                 PRINT_FIELD_U(" => ", sg_io, guard);
99                 return RVAL_IOCTL_DECODED;
100         }
101
102         PRINT_FIELD_U(", ", sg_io, response_len);
103         PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, response, sg_io.response_len,
104                                  0, tcp);
105         din_len = sg_io.din_xfer_len;
106         if (sg_io.din_resid > 0 && (unsigned int) sg_io.din_resid <= din_len)
107                 din_len -= sg_io.din_resid;
108         PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, din_xferp, din_len,
109                                  sg_io.din_iovec_count, tcp);
110         PRINT_FIELD_X(", ", sg_io, driver_status);
111         PRINT_FIELD_X(", ", sg_io, transport_status);
112         PRINT_FIELD_X(", ", sg_io, device_status);
113         PRINT_FIELD_U(", ", sg_io, retry_delay);
114         PRINT_FIELD_FLAGS(", ", sg_io, info, sg_io_info, "SG_INFO_???");
115         PRINT_FIELD_U(", ", sg_io, duration);
116         PRINT_FIELD_U(", ", sg_io, response_len);
117         PRINT_FIELD_D(", ", sg_io, din_resid);
118         PRINT_FIELD_D(", ", sg_io, dout_resid);
119         PRINT_FIELD_X(", ", sg_io, generated_tag);
120
121         return RVAL_IOCTL_DECODED;
122 }
123
124 #else /* !HAVE_LINUX_BSG_H */
125
126 static int
127 decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
128 {
129         tprints("{guard='Q', ...}");
130         return RVAL_IOCTL_DECODED;
131 }
132
133 static int
134 decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
135 {
136         return 0;
137 }
138
139 #endif
140
141 int
142 decode_sg_io_v4(struct tcb *const tcp, const kernel_ulong_t arg)
143 {
144         return entering(tcp) ? decode_request(tcp, arg)
145                              : decode_response(tcp, arg);
146 }