block.c revision ed720fda5d515f1359fcd3242223e553d1216789
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 <stdint.h> 30#include <inttypes.h> 31#include <linux/blkpg.h> 32#include <linux/fs.h> 33#include <linux/hdreg.h> 34 35/* ioctls <= 114 are present in Linux 2.4. The following ones have been 36 * added since then and headers containing them may not be available on 37 * every system. */ 38 39#define BLKTRACE_BDEV_SIZE 32 40struct blk_user_trace_setup { 41 char name[BLKTRACE_BDEV_SIZE]; /* output */ 42 uint16_t act_mask; /* input */ 43 uint32_t buf_size; /* input */ 44 uint32_t buf_nr; /* input */ 45 uint64_t start_lba; 46 uint64_t end_lba; 47 uint32_t pid; 48}; 49 50#ifndef BLKTRACESETUP 51#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) 52#endif 53#ifndef BLKTRACESTART 54#define BLKTRACESTART _IO(0x12,116) 55#endif 56#ifndef BLKTRACESTOP 57#define BLKTRACESTOP _IO(0x12,117) 58#endif 59#ifndef BLKTRACETEARDOWN 60#define BLKTRACETEARDOWN _IO(0x12,118) 61#endif 62#ifndef BLKDISCARD 63#define BLKDISCARD _IO(0x12,119) 64#endif 65#ifndef BLKIOMIN 66#define BLKIOMIN _IO(0x12,120) 67#endif 68#ifndef BLKIOOPT 69#define BLKIOOPT _IO(0x12,121) 70#endif 71#ifndef BLKALIGNOFF 72#define BLKALIGNOFF _IO(0x12,122) 73#endif 74#ifndef BLKPBSZGET 75#define BLKPBSZGET _IO(0x12,123) 76#endif 77#ifndef BLKDISCARDZEROES 78#define BLKDISCARDZEROES _IO(0x12,124) 79#endif 80#ifndef BLKSECDISCARD 81#define BLKSECDISCARD _IO(0x12,125) 82#endif 83 84static const struct xlat blkpg_ops[] = { 85 { BLKPG_ADD_PARTITION, "BLKPG_ADD_PARTITION", }, 86 { BLKPG_DEL_PARTITION, "BLKPG_DEL_PARTITION", }, 87 { 0, NULL }, 88}; 89 90static void 91print_blkpg_req(struct tcb *tcp, struct blkpg_ioctl_arg *blkpg) 92{ 93 struct blkpg_partition p; 94 95 tprints("{"); 96 printxval(blkpg_ops, blkpg->op, "BLKPG_???"); 97 98 tprintf(", flags=%d, datalen=%d, ", 99 blkpg->flags, blkpg->datalen); 100 101 if (umove(tcp, (long) blkpg->data, &p) < 0) 102 tprintf("%#lx}", (long) blkpg->data); 103 else 104 tprintf("{start=%lld, length=%lld, pno=%d, " 105 "devname=\"%.*s\", volname=\"%.*s\"}}", 106 p.start, p.length, p.pno, 107 (int) sizeof(p.devname), p.devname, 108 (int) sizeof(p.volname), p.volname); 109} 110 111int 112block_ioctl(struct tcb *tcp, long code, long arg) 113{ 114 switch (code) { 115 /* take arg as a value, not as a pointer */ 116 case BLKRASET: 117 case BLKFRASET: 118 if (entering(tcp)) 119 tprintf(", %ld", arg); 120 break; 121 122 /* take a signed int */ 123 case BLKROSET: 124 case BLKBSZSET: 125 if (entering(tcp)) { 126 int val; 127 if (umove(tcp, arg, &val) < 0) 128 tprintf(", %#lx", arg); 129 else 130 tprintf(", %d", val); 131 } 132 break; 133 134 /* returns an unsigned short */ 135 case BLKSECTGET: 136 if (exiting(tcp)) { 137 unsigned short val; 138 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 139 tprintf(", %#lx", arg); 140 else 141 tprintf(", %hu", val); 142 } 143 break; 144 145 /* return a signed int */ 146 case BLKROGET: 147 case BLKBSZGET: 148 case BLKSSZGET: 149 case BLKALIGNOFF: 150 if (exiting(tcp)) { 151 int val; 152 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 153 tprintf(", %#lx", arg); 154 else 155 tprintf(", %d", val); 156 } 157 break; 158 159 /* return an unsigned int */ 160 case BLKPBSZGET: 161 case BLKIOMIN: 162 case BLKIOOPT: 163 case BLKDISCARDZEROES: 164 if (exiting(tcp)) { 165 unsigned int val; 166 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 167 tprintf(", %#lx", arg); 168 else 169 tprintf(", %u", val); 170 } 171 break; 172 173 /* return a signed long */ 174 case BLKRAGET: 175 case BLKFRAGET: 176 if (exiting(tcp)) { 177 long val; 178 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 179 tprintf(", %#lx", arg); 180 else 181 tprintf(", %ld", val); 182 } 183 break; 184 185 /* returns an unsigned long */ 186 case BLKGETSIZE: 187 if (exiting(tcp)) { 188 unsigned long val; 189 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 190 tprintf(", %#lx", arg); 191 else 192 tprintf(", %lu", val); 193 } 194 break; 195 196#ifdef HAVE_BLKGETSIZE64 197 /* return an uint64_t */ 198 case BLKGETSIZE64: 199 if (exiting(tcp)) { 200 uint64_t val; 201 if (syserror(tcp) || umove(tcp, arg, &val) < 0) 202 tprintf(", %#lx", arg); 203 else 204 tprintf(", %" PRIu64, val); 205 } 206 break; 207#endif 208 209 /* More complex types */ 210 case BLKDISCARD: 211 case BLKSECDISCARD: 212 if (entering(tcp)) { 213 uint64_t range[2]; 214 if (umove(tcp, arg, range) < 0) 215 tprintf(", %#lx", arg); 216 else 217 tprintf(", {%" PRIx64 ", %" PRIx64 "}", 218 range[0], range[1]); 219 } 220 break; 221 222 case HDIO_GETGEO: 223 if (exiting(tcp)) { 224 struct hd_geometry geo; 225 if (syserror(tcp) || umove(tcp, arg, &geo) < 0) 226 tprintf(", %#lx", arg); 227 else 228 tprintf(", {heads=%hhu, sectors=%hhu, " 229 "cylinders=%hu, start=%lu}", 230 geo.heads, geo.sectors, 231 geo.cylinders, geo.start); 232 } 233 break; 234 235 case BLKPG: 236 if (entering(tcp)) { 237 struct blkpg_ioctl_arg blkpg; 238 if (umove(tcp, arg, &blkpg) < 0) 239 tprintf(", %#lx", arg); 240 else { 241 tprints(", "); 242 print_blkpg_req(tcp, &blkpg); 243 } 244 } 245 break; 246 247 case BLKTRACESETUP: 248 if (entering(tcp)) { 249 struct blk_user_trace_setup buts; 250 if (umove(tcp, arg, &buts) < 0) 251 tprintf(", %#lx", arg); 252 else 253 tprintf(", {act_mask=%hu, buf_size=%u, " 254 "buf_nr=%u, start_lba=%" PRIu64 ", " 255 "end_lba=%" PRIu64 ", pid=%u}", 256 buts.act_mask, buts.buf_size, 257 buts.buf_nr, buts.start_lba, 258 buts.end_lba, buts.pid); 259 } 260 if (exiting(tcp)) { 261 struct blk_user_trace_setup buts; 262 if (syserror(tcp) || umove(tcp, arg, &buts) < 0) 263 tprintf(", %#lx", arg); 264 else 265 tprintf(", {name=\"%.*s\"}", 266 (int) sizeof(buts.name), buts.name); 267 } 268 break; 269 270 /* No arguments or unhandled */ 271 case BLKTRACESTART: 272 case BLKTRACESTOP: 273 case BLKTRACETEARDOWN: 274 case BLKFLSBUF: /* Requires driver knowlege */ 275 case BLKRRPART: /* No args */ 276 default: 277 if (entering(tcp)) 278 tprintf(", %#lx", arg); 279 break; 280 281 }; 282 return 1; 283} 284