1 /* 2 * Copyright (c) 2007 Vladimir Nadvornik <nadvornik (at) suse.cz> 3 * Copyright (c) 2007-2017 Dmitry V. Levin <ldv (at) altlinux.org> 4 * Copyright (c) 2015 Bart Van Assche <bart.vanassche (at) sandisk.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "defs.h" 31 32 #ifdef HAVE_SCSI_SG_H 33 34 #include DEF_MPERS_TYPE(struct_sg_io_hdr) 35 36 # include <scsi/sg.h> 37 38 typedef struct sg_io_hdr struct_sg_io_hdr; 39 40 #endif /* HAVE_SCSI_SG_H */ 41 42 #include MPERS_DEFS 43 44 #include "xlat/sg_io_info.h" 45 46 #ifdef HAVE_SCSI_SG_H 47 # include "print_fields.h" 48 # include "xlat/sg_io_dxfer_direction.h" 49 # include "xlat/sg_io_flags.h" 50 51 static void 52 print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr, 53 const unsigned int data_size, const unsigned int iovec_count) 54 { 55 if (iovec_count) { 56 tprint_iov_upto(tcp, iovec_count, addr, IOV_DECODE_STR, 57 data_size); 58 } else { 59 printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX); 60 } 61 } 62 63 #define PRINT_FIELD_SG_IO_BUFFER(prefix_, where_, field_, size_, count_, tcp_) \ 64 do { \ 65 STRACE_PRINTF("%s%s=", (prefix_), #field_); \ 66 print_sg_io_buffer((tcp_), (mpers_ptr_t)((where_).field_), \ 67 (size_), (count_)); \ 68 } while (0) 69 70 static int 71 decode_request(struct tcb *const tcp, const kernel_ulong_t arg) 72 { 73 struct_sg_io_hdr sg_io; 74 static const size_t skip_iid = 75 offsetof(struct_sg_io_hdr, dxfer_direction); 76 77 tprints("{interface_id='S', "); 78 if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid, 79 &sg_io.dxfer_direction)) { 80 tprints("}"); 81 return RVAL_IOCTL_DECODED; 82 } 83 84 PRINT_FIELD_XVAL("", sg_io, dxfer_direction, sg_io_dxfer_direction, 85 "SG_DXFER_???"); 86 PRINT_FIELD_U(", ", sg_io, cmd_len); 87 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, cmdp, sg_io.cmd_len, 0, tcp); 88 PRINT_FIELD_U(", ", sg_io, mx_sb_len); 89 PRINT_FIELD_U(", ", sg_io, iovec_count); 90 PRINT_FIELD_U(", ", sg_io, dxfer_len); 91 PRINT_FIELD_U(", ", sg_io, timeout); 92 PRINT_FIELD_FLAGS(", ", sg_io, flags, sg_io_flags, "SG_FLAG_???"); 93 94 if (sg_io.dxfer_direction == SG_DXFER_TO_DEV || 95 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) { 96 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, dxferp, sg_io.dxfer_len, sg_io.iovec_count, tcp); 97 } 98 99 struct_sg_io_hdr *entering_sg_io = malloc(sizeof(*entering_sg_io)); 100 if (entering_sg_io) { 101 memcpy(entering_sg_io, &sg_io, sizeof(sg_io)); 102 entering_sg_io->interface_id = (unsigned char) 'S'; 103 set_tcb_priv_data(tcp, entering_sg_io, free); 104 } 105 106 return 0; 107 } 108 109 static int 110 decode_response(struct tcb *const tcp, const kernel_ulong_t arg) 111 { 112 struct_sg_io_hdr *entering_sg_io = get_tcb_priv_data(tcp); 113 struct_sg_io_hdr sg_io; 114 115 if (umove(tcp, arg, &sg_io) < 0) { 116 /* print i/o fields fetched on entering syscall */ 117 if (entering_sg_io->dxfer_direction == SG_DXFER_FROM_DEV) 118 PRINT_FIELD_PTR(", ", *entering_sg_io, dxferp); 119 PRINT_FIELD_PTR(", ", *entering_sg_io, sbp); 120 return RVAL_IOCTL_DECODED; 121 } 122 123 if (sg_io.interface_id != entering_sg_io->interface_id) { 124 PRINT_FIELD_U(" => ", sg_io, interface_id); 125 return RVAL_IOCTL_DECODED; 126 } 127 128 if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV || 129 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) { 130 uint32_t din_len = sg_io.dxfer_len; 131 const char *prefix = NULL; 132 133 if (sg_io.resid > 0 && (unsigned int) sg_io.resid <= din_len) 134 din_len -= sg_io.resid; 135 136 if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV) 137 prefix = ", "; 138 else if (din_len) 139 prefix = " => "; 140 141 if (prefix) { 142 tprints(prefix); 143 PRINT_FIELD_SG_IO_BUFFER("", sg_io, dxferp, din_len, 144 sg_io.iovec_count, tcp); 145 } 146 } 147 PRINT_FIELD_X(", ", sg_io, status); 148 PRINT_FIELD_X(", ", sg_io, masked_status); 149 PRINT_FIELD_X(", ", sg_io, msg_status); 150 PRINT_FIELD_U(", ", sg_io, sb_len_wr); 151 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, sbp, sg_io.sb_len_wr, 0, tcp); 152 PRINT_FIELD_X(", ", sg_io, host_status); 153 PRINT_FIELD_X(", ", sg_io, driver_status); 154 PRINT_FIELD_D(", ", sg_io, resid); 155 PRINT_FIELD_U(", ", sg_io, duration); 156 PRINT_FIELD_FLAGS(", ", sg_io, info, sg_io_info, "SG_INFO_???"); 157 158 return RVAL_IOCTL_DECODED; 159 } 160 161 #else /* !HAVE_SCSI_SG_H */ 162 163 static int 164 decode_request(struct tcb *const tcp, const kernel_ulong_t arg) 165 { 166 tprints("{interface_id='S', ...}"); 167 return RVAL_IOCTL_DECODED; 168 } 169 170 static int 171 decode_response(struct tcb *const tcp, const kernel_ulong_t arg) 172 { 173 return 0; 174 } 175 176 #endif 177 178 MPERS_PRINTER_DECL(int, decode_sg_io_v3, 179 struct tcb *const tcp, const kernel_ulong_t arg) 180 { 181 return entering(tcp) ? decode_request(tcp, arg) 182 : decode_response(tcp, arg); 183 } 184