1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "defs.h" 32 #include <linux/aio_abi.h> 33 34 SYS_FUNC(io_setup) 35 { 36 if (entering(tcp)) 37 tprintf("%u, ", (unsigned int) tcp->u_arg[0]); 38 else 39 printnum_ptr(tcp, tcp->u_arg[1]); 40 return 0; 41 } 42 43 SYS_FUNC(io_destroy) 44 { 45 printaddr(tcp->u_arg[0]); 46 47 return RVAL_DECODED; 48 } 49 50 enum iocb_sub { 51 SUB_NONE, SUB_COMMON, SUB_VECTOR 52 }; 53 54 static enum iocb_sub 55 tprint_lio_opcode(unsigned cmd) 56 { 57 static const struct { 58 const char *name; 59 enum iocb_sub sub; 60 } cmds[] = { 61 { "pread", SUB_COMMON }, 62 { "pwrite", SUB_COMMON }, 63 { "fsync", SUB_NONE }, 64 { "fdsync", SUB_NONE }, 65 { "preadx", SUB_NONE }, 66 { "poll", SUB_NONE }, 67 { "noop", SUB_NONE }, 68 { "preadv", SUB_VECTOR }, 69 { "pwritev", SUB_VECTOR }, 70 }; 71 72 if (cmd < ARRAY_SIZE(cmds)) { 73 tprints(cmds[cmd].name); 74 return cmds[cmd].sub; 75 } 76 tprintf("%u /* SUB_??? */", cmd); 77 return SUB_NONE; 78 } 79 80 static void 81 print_common_flags(struct tcb *tcp, const struct iocb *cb) 82 { 83 /* IOCB_FLAG_RESFD is available since v2.6.22-rc1~47 */ 84 #ifdef IOCB_FLAG_RESFD 85 if (cb->aio_flags & IOCB_FLAG_RESFD) { 86 tprints(", resfd="); 87 printfd(tcp, cb->aio_resfd); 88 } 89 if (cb->aio_flags & ~IOCB_FLAG_RESFD) 90 tprintf(", flags=%#x", cb->aio_flags); 91 #endif 92 } 93 94 static bool 95 iocb_is_valid(const struct iocb *cb) 96 { 97 return cb->aio_buf == (unsigned long) cb->aio_buf && 98 cb->aio_nbytes == (size_t) cb->aio_nbytes && 99 (ssize_t) cb->aio_nbytes >= 0; 100 } 101 102 static enum iocb_sub 103 print_iocb_header(struct tcb *tcp, const struct iocb *cb) 104 { 105 enum iocb_sub sub; 106 107 if (cb->aio_data) 108 tprintf("data=%#" PRIx64 ", ", 109 (uint64_t) cb->aio_data); 110 111 if (cb->aio_key) 112 tprintf("key=%u, ", cb->aio_key); 113 114 sub = tprint_lio_opcode(cb->aio_lio_opcode); 115 if (cb->aio_reqprio) 116 tprintf(", reqprio=%hd", cb->aio_reqprio); 117 118 tprints(", fildes="); 119 printfd(tcp, cb->aio_fildes); 120 121 return sub; 122 } 123 124 static void 125 print_iocb(struct tcb *tcp, const struct iocb *cb) 126 { 127 enum iocb_sub sub = print_iocb_header(tcp, cb); 128 129 switch (sub) { 130 case SUB_COMMON: 131 if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) { 132 tprints(", str="); 133 printstrn(tcp, cb->aio_buf, cb->aio_nbytes); 134 } else { 135 tprintf(", buf=%#" PRIx64, (uint64_t) cb->aio_buf); 136 } 137 tprintf(", nbytes=%" PRIu64 ", offset=%" PRId64, 138 (uint64_t) cb->aio_nbytes, (int64_t) cb->aio_offset); 139 print_common_flags(tcp, cb); 140 break; 141 case SUB_VECTOR: 142 if (iocb_is_valid(cb)) { 143 tprints(", iovec="); 144 tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf, 145 cb->aio_lio_opcode == 8 146 ? IOV_DECODE_STR 147 : IOV_DECODE_ADDR); 148 } else { 149 tprintf(", buf=%#" PRIx64 ", nbytes=%" PRIu64, 150 (uint64_t) cb->aio_buf, 151 (uint64_t) cb->aio_nbytes); 152 } 153 tprintf(", offset=%" PRId64, (int64_t) cb->aio_offset); 154 print_common_flags(tcp, cb); 155 break; 156 case SUB_NONE: 157 break; 158 } 159 } 160 161 static bool 162 print_iocbp(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 163 { 164 kernel_ulong_t addr; 165 struct iocb cb; 166 167 if (elem_size < sizeof(kernel_ulong_t)) { 168 addr = * (unsigned int *) elem_buf; 169 } else { 170 addr = * (kernel_ulong_t *) elem_buf; 171 } 172 173 tprints("{"); 174 if (!umove_or_printaddr(tcp, addr, &cb)) 175 print_iocb(tcp, &cb); 176 tprints("}"); 177 178 return true; 179 } 180 181 SYS_FUNC(io_submit) 182 { 183 const kernel_long_t nr = 184 truncate_klong_to_current_wordsize(tcp->u_arg[1]); 185 const kernel_ulong_t addr = tcp->u_arg[2]; 186 kernel_ulong_t iocbp; 187 188 printaddr(tcp->u_arg[0]); 189 tprintf(", %" PRI_kld ", ", nr); 190 191 if (nr < 0) 192 printaddr(addr); 193 else 194 print_array(tcp, addr, nr, &iocbp, current_wordsize, 195 umoven_or_printaddr, print_iocbp, 0); 196 197 return RVAL_DECODED; 198 } 199 200 static bool 201 print_io_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 202 { 203 struct io_event *event = elem_buf; 204 205 tprintf("{data=%#" PRIx64 ", obj=%#" PRIx64 206 ", res=%" PRId64 ", res2=%" PRId64 "}", 207 (uint64_t) event->data, (uint64_t) event->obj, 208 (int64_t) event->res, (int64_t) event->res2); 209 210 return true; 211 } 212 213 SYS_FUNC(io_cancel) 214 { 215 if (entering(tcp)) { 216 printaddr(tcp->u_arg[0]); 217 tprints(", "); 218 219 struct iocb cb; 220 221 if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) { 222 tprints("{"); 223 print_iocb_header(tcp, &cb); 224 tprints("}"); 225 } 226 tprints(", "); 227 } else { 228 struct io_event event; 229 230 if (!umove_or_printaddr(tcp, tcp->u_arg[2], &event)) 231 print_io_event(tcp, &event, sizeof(event), 0); 232 } 233 return 0; 234 } 235 236 SYS_FUNC(io_getevents) 237 { 238 if (entering(tcp)) { 239 printaddr(tcp->u_arg[0]); 240 tprintf(", %" PRI_kld ", %" PRI_kld ", ", 241 truncate_klong_to_current_wordsize(tcp->u_arg[1]), 242 truncate_klong_to_current_wordsize(tcp->u_arg[2])); 243 } else { 244 struct io_event buf; 245 print_array(tcp, tcp->u_arg[3], tcp->u_rval, &buf, sizeof(buf), 246 umoven_or_printaddr, print_io_event, 0); 247 tprints(", "); 248 /* 249 * Since the timeout parameter is read by the kernel 250 * on entering syscall, it has to be decoded the same way 251 * whether the syscall has failed or not. 252 */ 253 temporarily_clear_syserror(tcp); 254 print_timespec(tcp, tcp->u_arg[4]); 255 restore_cleared_syserror(tcp); 256 } 257 return 0; 258 } 259