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 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "defs.h" 30 31 #include DEF_MPERS_TYPE(struct_blk_user_trace_setup) 32 #include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg) 33 #include DEF_MPERS_TYPE(struct_blkpg_partition) 34 35 #include <linux/ioctl.h> 36 #include <linux/fs.h> 37 38 typedef struct { 39 int op; 40 int flags; 41 int datalen; 42 void *data; 43 } struct_blkpg_ioctl_arg; 44 45 #define BLKPG_DEVNAMELTH 64 46 #define BLKPG_VOLNAMELTH 64 47 typedef struct { 48 int64_t start; /* starting offset in bytes */ 49 int64_t length; /* length in bytes */ 50 int pno; /* partition number */ 51 char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2, 52 to be used in kernel messages */ 53 char volname[BLKPG_VOLNAMELTH]; /* volume label */ 54 } struct_blkpg_partition; 55 56 #define BLKTRACE_BDEV_SIZE 32 57 typedef struct blk_user_trace_setup { 58 char name[BLKTRACE_BDEV_SIZE]; /* output */ 59 uint16_t act_mask; /* input */ 60 uint32_t buf_size; /* input */ 61 uint32_t buf_nr; /* input */ 62 uint64_t start_lba; 63 uint64_t end_lba; 64 uint32_t pid; 65 } struct_blk_user_trace_setup; 66 67 #include MPERS_DEFS 68 69 #ifndef BLKPG 70 # define BLKPG _IO(0x12,105) 71 #endif 72 73 /* 74 * ioctl numbers <= 114 are present in Linux 2.4. The following ones have been 75 * added since then and headers containing them may not be available on every 76 * system. 77 */ 78 79 #ifndef BLKTRACESETUP 80 # define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup) 81 #endif 82 #ifndef BLKTRACESTART 83 # define BLKTRACESTART _IO(0x12,116) 84 #endif 85 #ifndef BLKTRACESTOP 86 # define BLKTRACESTOP _IO(0x12,117) 87 #endif 88 #ifndef BLKTRACETEARDOWN 89 # define BLKTRACETEARDOWN _IO(0x12,118) 90 #endif 91 #ifndef BLKDISCARD 92 # define BLKDISCARD _IO(0x12,119) 93 #endif 94 #ifndef BLKIOMIN 95 # define BLKIOMIN _IO(0x12,120) 96 #endif 97 #ifndef BLKIOOPT 98 # define BLKIOOPT _IO(0x12,121) 99 #endif 100 #ifndef BLKALIGNOFF 101 # define BLKALIGNOFF _IO(0x12,122) 102 #endif 103 #ifndef BLKPBSZGET 104 # define BLKPBSZGET _IO(0x12,123) 105 #endif 106 #ifndef BLKDISCARDZEROES 107 # define BLKDISCARDZEROES _IO(0x12,124) 108 #endif 109 #ifndef BLKSECDISCARD 110 # define BLKSECDISCARD _IO(0x12,125) 111 #endif 112 #ifndef BLKROTATIONAL 113 # define BLKROTATIONAL _IO(0x12,126) 114 #endif 115 #ifndef BLKZEROOUT 116 # define BLKZEROOUT _IO(0x12,127) 117 #endif 118 119 #include "xlat/blkpg_ops.h" 120 121 static void 122 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg) 123 { 124 struct_blkpg_partition p; 125 126 tprints("{"); 127 printxval(blkpg_ops, blkpg->op, "BLKPG_???"); 128 129 tprintf(", flags=%d, datalen=%d, data=", 130 blkpg->flags, blkpg->datalen); 131 132 if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) { 133 tprintf("{start=%" PRId64 ", length=%" PRId64 134 ", pno=%d, devname=", 135 p.start, p.length, p.pno); 136 print_quoted_string(p.devname, sizeof(p.devname), 137 QUOTE_0_TERMINATED); 138 tprints(", volname="); 139 print_quoted_string(p.volname, sizeof(p.volname), 140 QUOTE_0_TERMINATED); 141 tprints("}"); 142 } 143 tprints("}"); 144 } 145 146 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp, 147 const unsigned int code, const kernel_ulong_t arg) 148 { 149 switch (code) { 150 /* take arg as a value, not as a pointer */ 151 case BLKRASET: 152 case BLKFRASET: 153 tprintf(", %" PRI_klu, arg); 154 break; 155 156 /* return an unsigned short */ 157 case BLKSECTGET: 158 case BLKROTATIONAL: 159 if (entering(tcp)) 160 return 0; 161 tprints(", "); 162 printnum_short(tcp, arg, "%hu"); 163 break; 164 165 /* return a signed int */ 166 case BLKROGET: 167 case BLKBSZGET: 168 case BLKSSZGET: 169 case BLKALIGNOFF: 170 if (entering(tcp)) 171 return 0; 172 /* fall through */ 173 /* take a signed int */ 174 case BLKROSET: 175 case BLKBSZSET: 176 tprints(", "); 177 printnum_int(tcp, arg, "%d"); 178 break; 179 180 /* return an unsigned int */ 181 case BLKPBSZGET: 182 case BLKIOMIN: 183 case BLKIOOPT: 184 case BLKDISCARDZEROES: 185 if (entering(tcp)) 186 return 0; 187 tprints(", "); 188 printnum_int(tcp, arg, "%u"); 189 break; 190 191 /* return a signed long */ 192 case BLKRAGET: 193 case BLKFRAGET: 194 if (entering(tcp)) 195 return 0; 196 tprints(", "); 197 printnum_slong(tcp, arg); 198 break; 199 200 /* returns an unsigned long */ 201 case BLKGETSIZE: 202 if (entering(tcp)) 203 return 0; 204 tprints(", "); 205 printnum_ulong(tcp, arg); 206 break; 207 208 #ifdef HAVE_BLKGETSIZE64 209 /* returns an uint64_t */ 210 case BLKGETSIZE64: 211 if (entering(tcp)) 212 return 0; 213 tprints(", "); 214 printnum_int64(tcp, arg, "%" PRIu64); 215 break; 216 #endif 217 218 /* takes a pair of uint64_t */ 219 case BLKDISCARD: 220 case BLKSECDISCARD: 221 case BLKZEROOUT: 222 tprints(", "); 223 printpair_int64(tcp, arg, "%" PRIu64); 224 break; 225 226 /* More complex types */ 227 case BLKPG: { 228 struct_blkpg_ioctl_arg blkpg; 229 230 tprints(", "); 231 if (!umove_or_printaddr(tcp, arg, &blkpg)) 232 print_blkpg_req(tcp, &blkpg); 233 break; 234 } 235 236 case BLKTRACESETUP: 237 if (entering(tcp)) { 238 struct_blk_user_trace_setup buts; 239 240 tprints(", "); 241 if (umove_or_printaddr(tcp, arg, &buts)) 242 break; 243 tprintf("{act_mask=%u, buf_size=%u, " 244 "buf_nr=%u, start_lba=%" PRIu64 ", " 245 "end_lba=%" PRIu64 ", pid=%u", 246 (unsigned)buts.act_mask, buts.buf_size, 247 buts.buf_nr, buts.start_lba, 248 buts.end_lba, buts.pid); 249 return 1; 250 } else { 251 struct_blk_user_trace_setup buts; 252 253 if (!syserror(tcp) && !umove(tcp, arg, &buts)) { 254 tprints(", name="); 255 print_quoted_string(buts.name, sizeof(buts.name), 256 QUOTE_0_TERMINATED); 257 } 258 tprints("}"); 259 break; 260 } 261 262 /* No arguments */ 263 case BLKRRPART: 264 case BLKFLSBUF: 265 case BLKTRACESTART: 266 case BLKTRACESTOP: 267 case BLKTRACETEARDOWN: 268 break; 269 default: 270 return RVAL_DECODED; 271 } 272 273 return RVAL_DECODED | 1; 274 } 275