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_ulong(tcp, tcp->u_arg[1]); 40 return 0; 41 } 42 43 SYS_FUNC(io_destroy) 44 { 45 tprintf("%lu", 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(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 tprintf(", resfd=%d", cb->aio_resfd); 87 if (cb->aio_flags & ~IOCB_FLAG_RESFD) 88 tprintf(", flags=%x", cb->aio_flags); 89 #endif 90 } 91 92 static bool 93 iocb_is_valid(const struct iocb *cb) 94 { 95 return cb->aio_buf == (unsigned long) cb->aio_buf && 96 cb->aio_nbytes == (size_t) cb->aio_nbytes && 97 (ssize_t) cb->aio_nbytes >= 0; 98 } 99 100 static enum iocb_sub 101 print_iocb_header(const struct iocb *cb) 102 { 103 enum iocb_sub sub; 104 105 if (cb->aio_data) 106 tprintf("data=%#" PRIx64 ", ", 107 (uint64_t) cb->aio_data); 108 109 if (cb->aio_key) 110 tprintf("key=%u, ", cb->aio_key); 111 112 sub = tprint_lio_opcode(cb->aio_lio_opcode); 113 if (cb->aio_reqprio) 114 tprintf(", reqprio=%hd", cb->aio_reqprio); 115 116 tprintf(", fildes=%d", cb->aio_fildes); 117 118 return sub; 119 } 120 121 static void 122 print_iocb(struct tcb *tcp, const struct iocb *cb) 123 { 124 enum iocb_sub sub = print_iocb_header(cb); 125 126 switch (sub) { 127 case SUB_COMMON: 128 if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) { 129 tprints(", str="); 130 printstr(tcp, (unsigned long) cb->aio_buf, 131 (unsigned long) cb->aio_nbytes); 132 } else { 133 tprintf(", buf=%#" PRIx64, (uint64_t) cb->aio_buf); 134 } 135 tprintf(", nbytes=%" PRIu64 ", offset=%" PRId64, 136 (uint64_t) cb->aio_nbytes, (int64_t) cb->aio_offset); 137 print_common_flags(cb); 138 break; 139 case SUB_VECTOR: 140 if (iocb_is_valid(cb)) { 141 tprints(", iovec="); 142 tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf, 143 cb->aio_lio_opcode == 8); 144 } else { 145 tprintf(", buf=%#" PRIx64 ", nbytes=%" PRIu64, 146 (uint64_t) cb->aio_buf, 147 (uint64_t) cb->aio_nbytes); 148 } 149 tprintf(", offset=%" PRId64, (int64_t) cb->aio_offset); 150 print_common_flags(cb); 151 break; 152 case SUB_NONE: 153 break; 154 } 155 } 156 157 SYS_FUNC(io_submit) 158 { 159 long nr = tcp->u_arg[1]; 160 /* if nr <= 0, we end up printing just "[]" */ 161 tprintf("%lu, %ld, [", tcp->u_arg[0], nr); 162 { 163 long i; 164 long iocbs = tcp->u_arg[2]; 165 166 for (i = 0; i < nr; ++i, iocbs += current_wordsize) { 167 unsigned long iocbp; 168 struct iocb cb; 169 170 if (i) 171 tprints(", "); 172 173 if (umove_ulong_or_printaddr(tcp, iocbs, &iocbp)) { 174 /* 175 * No point in trying to read the whole array 176 * because nr can be ridiculously large. 177 */ 178 break; 179 } 180 181 tprints("{"); 182 if (!umove_or_printaddr(tcp, iocbp, &cb)) 183 print_iocb(tcp, &cb); 184 tprints("}"); 185 } 186 } 187 tprints("]"); 188 return RVAL_DECODED; 189 } 190 191 static int 192 print_io_event(struct tcb *tcp, const long addr) 193 { 194 struct io_event event; 195 196 if (umove_or_printaddr(tcp, addr, &event)) 197 return -1; 198 tprintf("{data=%#" PRIx64 ", obj=%#" PRIx64 199 ", res=%" PRId64 ", res2=%" PRId64 "}", 200 (uint64_t) event.data, (uint64_t) event.obj, 201 (int64_t) event.res, (int64_t) event.res2); 202 return 0; 203 } 204 205 SYS_FUNC(io_cancel) 206 { 207 if (entering(tcp)) { 208 tprintf("%lu, ", tcp->u_arg[0]); 209 struct iocb cb; 210 211 if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) { 212 tprints("{"); 213 print_iocb_header(&cb); 214 tprints("}"); 215 } 216 tprints(", "); 217 } else { 218 print_io_event(tcp, tcp->u_arg[2]); 219 } 220 return 0; 221 } 222 223 SYS_FUNC(io_getevents) 224 { 225 if (entering(tcp)) { 226 tprintf("%lu, %ld, %ld, ", 227 tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); 228 } else { 229 if (tcp->u_rval == 0) { 230 tprints("[]"); 231 } else { 232 struct io_event *events = (void *)tcp->u_arg[3]; 233 long i, nr = tcp->u_rval; 234 235 for (i = 0; i < nr; i++, events++) { 236 if (i == 0) 237 tprints("["); 238 else 239 tprints(", "); 240 241 if (print_io_event(tcp, (long)events)) 242 break; 243 } 244 tprints("], "); 245 } 246 247 /* 248 * Since the timeout parameter is read by the kernel 249 * on entering syscall, it has to be decoded the same way 250 * whether the syscall has failed or not. 251 */ 252 temporarily_clear_syserror(tcp); 253 print_timespec(tcp, tcp->u_arg[4]); 254 restore_cleared_syserror(tcp); 255 } 256 return 0; 257 } 258