block.c revision 2479ef0bceaa35ea353fd0ea372cf31d5eb8a216
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#ifndef BLKROTATIONAL 82# define BLKROTATIONAL _IO(0x12,126) 83#endif 84#ifndef BLKZEROOUT 85# define BLKZEROOUT _IO(0x12,127) 86#endif 87 88#include "xlat/blkpg_ops.h" 89 90static void 91print_blkpg_req(struct tcb *tcp, const 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, data=", 99 blkpg->flags, blkpg->datalen); 100 101 if (!umove_or_printaddr(tcp, (long) blkpg->data, &p)) { 102 tprintf("{start=%lld, length=%lld, pno=%d, devname=", 103 p.start, p.length, p.pno); 104 print_quoted_string(p.devname, sizeof(p.devname), 105 QUOTE_0_TERMINATED); 106 tprints(", volname="); 107 print_quoted_string(p.volname, sizeof(p.volname), 108 QUOTE_0_TERMINATED); 109 tprints("}"); 110 } 111 tprints("}"); 112} 113 114int 115block_ioctl(struct tcb *tcp, const unsigned int code, const long arg) 116{ 117 switch (code) { 118 /* take arg as a value, not as a pointer */ 119 case BLKRASET: 120 case BLKFRASET: 121 tprintf(", %lu", arg); 122 break; 123 124 /* take a signed int */ 125 case BLKROSET: 126 case BLKBSZSET: 127 tprints(", "); 128 printnum_int(tcp, arg, "%d"); 129 break; 130 131 /* return an unsigned short */ 132 case BLKSECTGET: 133 case BLKROTATIONAL: 134 if (entering(tcp)) 135 return 0; 136 tprints(", "); 137 printnum_short(tcp, arg, "%hu"); 138 break; 139 140 /* return a signed int */ 141 case BLKROGET: 142 case BLKBSZGET: 143 case BLKSSZGET: 144 case BLKALIGNOFF: 145 if (entering(tcp)) 146 return 0; 147 tprints(", "); 148 printnum_int(tcp, arg, "%d"); 149 break; 150 151 /* return an unsigned int */ 152 case BLKPBSZGET: 153 case BLKIOMIN: 154 case BLKIOOPT: 155 case BLKDISCARDZEROES: 156 if (entering(tcp)) 157 return 0; 158 tprints(", "); 159 printnum_int(tcp, arg, "%u"); 160 break; 161 162 /* return a signed long */ 163 case BLKRAGET: 164 case BLKFRAGET: 165 if (entering(tcp)) 166 return 0; 167 tprints(", "); 168 printnum_slong(tcp, arg); 169 break; 170 171 /* returns an unsigned long */ 172 case BLKGETSIZE: 173 if (entering(tcp)) 174 return 0; 175 tprints(", "); 176 printnum_ulong(tcp, arg); 177 break; 178 179#ifdef HAVE_BLKGETSIZE64 180 /* returns an uint64_t */ 181 case BLKGETSIZE64: 182 if (entering(tcp)) 183 return 0; 184 tprints(", "); 185 printnum_int64(tcp, arg, "%" PRIu64); 186 break; 187#endif 188 189 /* takes a pair of uint64_t */ 190 case BLKDISCARD: 191 case BLKSECDISCARD: 192 case BLKZEROOUT: 193 tprints(", "); 194 printpair_int64(tcp, arg, "%" PRIx64); 195 break; 196 197 /* More complex types */ 198 case HDIO_GETGEO: 199 if (entering(tcp)) 200 return 0; 201 else { 202 struct hd_geometry geo; 203 204 tprints(", "); 205 if (!umove_or_printaddr(tcp, arg, &geo)) 206 tprintf("{heads=%u, sectors=%u, " 207 "cylinders=%u, start=%lu}", 208 (unsigned)geo.heads, 209 (unsigned)geo.sectors, 210 (unsigned)geo.cylinders, 211 geo.start); 212 } 213 break; 214 215 case BLKPG: { 216 struct blkpg_ioctl_arg blkpg; 217 218 tprints(", "); 219 if (!umove_or_printaddr(tcp, arg, &blkpg)) 220 print_blkpg_req(tcp, &blkpg); 221 break; 222 } 223 224 case BLKTRACESETUP: 225 if (entering(tcp)) { 226 struct blk_user_trace_setup buts; 227 228 tprints(", "); 229 if (umove_or_printaddr(tcp, arg, &buts)) 230 break; 231 tprintf("{act_mask=%u, buf_size=%u, " 232 "buf_nr=%u, start_lba=%" PRIu64 ", " 233 "end_lba=%" PRIu64 ", pid=%u", 234 (unsigned)buts.act_mask, buts.buf_size, 235 buts.buf_nr, buts.start_lba, 236 buts.end_lba, buts.pid); 237 return 1; 238 } else { 239 struct blk_user_trace_setup buts; 240 241 if (syserror(tcp)) { 242 tprints("}"); 243 break; 244 } 245 tprints(", "); 246 if (umove(tcp, arg, &buts) < 0) { 247 tprints("???}"); 248 break; 249 } 250 tprints(", name="); 251 print_quoted_string(buts.name, sizeof(buts.name), 252 QUOTE_0_TERMINATED); 253 tprints("}"); 254 break; 255 } 256 257#ifdef FITRIM 258 /* First seen in linux-2.6.37 */ 259 case FITRIM: { 260 struct fstrim_range fstrim; 261 262 tprints(", "); 263 if (!umove_or_printaddr(tcp, arg, &fstrim)) 264 tprintf("{start=%#" PRIx64 ", " 265 "len=%#" PRIx64 ", " 266 "minlen=%#" PRIx64 "}", 267 (uint64_t) fstrim.start, 268 (uint64_t) fstrim.len, 269 (uint64_t) fstrim.minlen); 270 break; 271 } 272#endif 273 274 /* No arguments */ 275 case BLKRRPART: 276 case BLKFLSBUF: 277 case BLKTRACESTART: 278 case BLKTRACESTOP: 279 case BLKTRACETEARDOWN: 280#ifdef FIFREEZE 281 case FIFREEZE: 282 case FITHAW: 283#endif 284 break; 285 default: 286 return RVAL_DECODED; 287 } 288 289 return RVAL_DECODED | 1; 290} 291