1 /* 2 * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm (at) suse.com> 3 * Copyright (c) 2011-2016 Dmitry V. Levin <ldv (at) altlinux.org> 4 * Copyright (c) 2011-2017 The strace developers. 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 #include DEF_MPERS_TYPE(struct_blk_user_trace_setup) 33 #include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg) 34 #include DEF_MPERS_TYPE(struct_blkpg_partition) 35 36 #include <linux/ioctl.h> 37 #include <linux/fs.h> 38 39 typedef struct { 40 int op; 41 int flags; 42 int datalen; 43 void *data; 44 } struct_blkpg_ioctl_arg; 45 46 #define BLKPG_DEVNAMELTH 64 47 #define BLKPG_VOLNAMELTH 64 48 typedef struct { 49 int64_t start; /* starting offset in bytes */ 50 int64_t length; /* length in bytes */ 51 int pno; /* partition number */ 52 char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2, 53 to be used in kernel messages */ 54 char volname[BLKPG_VOLNAMELTH]; /* volume label */ 55 } struct_blkpg_partition; 56 57 #define BLKTRACE_BDEV_SIZE 32 58 typedef struct blk_user_trace_setup { 59 char name[BLKTRACE_BDEV_SIZE]; /* output */ 60 uint16_t act_mask; /* input */ 61 uint32_t buf_size; /* input */ 62 uint32_t buf_nr; /* input */ 63 uint64_t start_lba; 64 uint64_t end_lba; 65 uint32_t pid; 66 } struct_blk_user_trace_setup; 67 68 #include MPERS_DEFS 69 70 #include "print_fields.h" 71 72 #ifndef BLKPG 73 # define BLKPG _IO(0x12, 105) 74 #endif 75 76 /* 77 * ioctl numbers <= 114 are present in Linux 2.4. The following ones have been 78 * added since then and headers containing them may not be available on every 79 * system. 80 */ 81 82 #ifndef BLKTRACESETUP 83 # define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup) 84 #endif 85 #ifndef BLKTRACESTART 86 # define BLKTRACESTART _IO(0x12, 116) 87 #endif 88 #ifndef BLKTRACESTOP 89 # define BLKTRACESTOP _IO(0x12, 117) 90 #endif 91 #ifndef BLKTRACETEARDOWN 92 # define BLKTRACETEARDOWN _IO(0x12, 118) 93 #endif 94 #ifndef BLKDISCARD 95 # define BLKDISCARD _IO(0x12, 119) 96 #endif 97 #ifndef BLKIOMIN 98 # define BLKIOMIN _IO(0x12, 120) 99 #endif 100 #ifndef BLKIOOPT 101 # define BLKIOOPT _IO(0x12, 121) 102 #endif 103 #ifndef BLKALIGNOFF 104 # define BLKALIGNOFF _IO(0x12, 122) 105 #endif 106 #ifndef BLKPBSZGET 107 # define BLKPBSZGET _IO(0x12, 123) 108 #endif 109 #ifndef BLKDISCARDZEROES 110 # define BLKDISCARDZEROES _IO(0x12, 124) 111 #endif 112 #ifndef BLKSECDISCARD 113 # define BLKSECDISCARD _IO(0x12, 125) 114 #endif 115 #ifndef BLKROTATIONAL 116 # define BLKROTATIONAL _IO(0x12, 126) 117 #endif 118 #ifndef BLKZEROOUT 119 # define BLKZEROOUT _IO(0x12, 127) 120 #endif 121 122 #include "xlat/blkpg_ops.h" 123 124 static void 125 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg) 126 { 127 struct_blkpg_partition p; 128 129 PRINT_FIELD_XVAL("{", *blkpg, op, blkpg_ops, "BLKPG_???"); 130 PRINT_FIELD_D(", ", *blkpg, flags); 131 PRINT_FIELD_D(", ", *blkpg, datalen); 132 133 tprints(", data="); 134 if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) { 135 PRINT_FIELD_D("{", p, start); 136 PRINT_FIELD_D(", ", p, length); 137 PRINT_FIELD_D(", ", p, pno); 138 PRINT_FIELD_CSTRING(", ", p, devname); 139 PRINT_FIELD_CSTRING(", ", p, volname); 140 tprints("}"); 141 } 142 tprints("}"); 143 } 144 145 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, 146 const unsigned int code, const kernel_ulong_t arg) 147 { 148 switch (code) { 149 /* take arg as a value, not as a pointer */ 150 case BLKRASET: 151 case BLKFRASET: 152 tprintf(", %" PRI_klu, arg); 153 break; 154 155 /* return an unsigned short */ 156 case BLKSECTGET: 157 case BLKROTATIONAL: 158 if (entering(tcp)) 159 return 0; 160 tprints(", "); 161 printnum_short(tcp, arg, "%hu"); 162 break; 163 164 /* return a signed int */ 165 case BLKROGET: 166 case BLKBSZGET: 167 case BLKSSZGET: 168 case BLKALIGNOFF: 169 if (entering(tcp)) 170 return 0; 171 /* fall through */ 172 /* take a signed int */ 173 case BLKROSET: 174 case BLKBSZSET: 175 tprints(", "); 176 printnum_int(tcp, arg, "%d"); 177 break; 178 179 /* return an unsigned int */ 180 case BLKPBSZGET: 181 case BLKIOMIN: 182 case BLKIOOPT: 183 case BLKDISCARDZEROES: 184 if (entering(tcp)) 185 return 0; 186 tprints(", "); 187 printnum_int(tcp, arg, "%u"); 188 break; 189 190 /* return a signed long */ 191 case BLKRAGET: 192 case BLKFRAGET: 193 if (entering(tcp)) 194 return 0; 195 tprints(", "); 196 printnum_slong(tcp, arg); 197 break; 198 199 /* returns an unsigned long */ 200 case BLKGETSIZE: 201 if (entering(tcp)) 202 return 0; 203 tprints(", "); 204 printnum_ulong(tcp, arg); 205 break; 206 207 #ifdef HAVE_BLKGETSIZE64 208 /* returns an uint64_t */ 209 case BLKGETSIZE64: 210 if (entering(tcp)) 211 return 0; 212 tprints(", "); 213 printnum_int64(tcp, arg, "%" PRIu64); 214 break; 215 #endif 216 217 /* takes a pair of uint64_t */ 218 case BLKDISCARD: 219 case BLKSECDISCARD: 220 case BLKZEROOUT: 221 tprints(", "); 222 printpair_int64(tcp, arg, "%" PRIu64); 223 break; 224 225 /* More complex types */ 226 case BLKPG: { 227 struct_blkpg_ioctl_arg blkpg; 228 229 tprints(", "); 230 if (!umove_or_printaddr(tcp, arg, &blkpg)) 231 print_blkpg_req(tcp, &blkpg); 232 break; 233 } 234 235 case BLKTRACESETUP: 236 if (entering(tcp)) { 237 struct_blk_user_trace_setup buts; 238 239 tprints(", "); 240 if (umove_or_printaddr(tcp, arg, &buts)) 241 break; 242 PRINT_FIELD_U("{", buts, act_mask); 243 PRINT_FIELD_U(", ", buts, buf_size); 244 PRINT_FIELD_U(", ", buts, buf_nr); 245 PRINT_FIELD_U(", ", buts, start_lba); 246 PRINT_FIELD_U(", ", buts, end_lba); 247 PRINT_FIELD_U(", ", buts, pid); 248 return 0; 249 } else { 250 struct_blk_user_trace_setup buts; 251 252 if (!syserror(tcp) && !umove(tcp, arg, &buts)) 253 PRINT_FIELD_CSTRING(", ", buts, name); 254 tprints("}"); 255 break; 256 } 257 258 /* No arguments */ 259 case BLKRRPART: 260 case BLKFLSBUF: 261 case BLKTRACESTART: 262 case BLKTRACESTOP: 263 case BLKTRACETEARDOWN: 264 break; 265 default: 266 return RVAL_DECODED; 267 } 268 269 return RVAL_IOCTL_DECODED; 270 } 271