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