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