blob: 4d1a965b40b59d83210047f2e308e9f2b7e944ac [file] [log] [blame]
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +00001/*
2 * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +00003 * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@altlinux.org>
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +00004 * 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"
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000030
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
Elliott Hughesd35df492017-02-15 15:19:05 -080035#include <linux/ioctl.h>
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000036#include <linux/fs.h>
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000037
Elliott Hughesd35df492017-02-15 15:19:05 -080038typedef 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
47typedef 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
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000056#define BLKTRACE_BDEV_SIZE 32
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000057typedef struct blk_user_trace_setup {
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000058 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;
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000065} struct_blk_user_trace_setup;
66
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000067#include MPERS_DEFS
68
Elliott Hughesd35df492017-02-15 15:19:05 -080069#ifndef BLKPG
70# define BLKPG _IO(0x12,105)
71#endif
72
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000073/*
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 */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000078
79#ifndef BLKTRACESETUP
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +000080# define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000081#endif
82#ifndef BLKTRACESTART
Dmitry V. Levina0beac12015-07-05 15:15:03 +030083# define BLKTRACESTART _IO(0x12,116)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000084#endif
Dmitry V. Levin4cee0af2011-04-07 19:58:10 +000085#ifndef BLKTRACESTOP
Dmitry V. Levina0beac12015-07-05 15:15:03 +030086# define BLKTRACESTOP _IO(0x12,117)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000087#endif
88#ifndef BLKTRACETEARDOWN
Dmitry V. Levina0beac12015-07-05 15:15:03 +030089# define BLKTRACETEARDOWN _IO(0x12,118)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000090#endif
91#ifndef BLKDISCARD
Dmitry V. Levina0beac12015-07-05 15:15:03 +030092# define BLKDISCARD _IO(0x12,119)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000093#endif
94#ifndef BLKIOMIN
Dmitry V. Levina0beac12015-07-05 15:15:03 +030095# define BLKIOMIN _IO(0x12,120)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000096#endif
97#ifndef BLKIOOPT
Dmitry V. Levina0beac12015-07-05 15:15:03 +030098# define BLKIOOPT _IO(0x12,121)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +000099#endif
100#ifndef BLKALIGNOFF
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300101# define BLKALIGNOFF _IO(0x12,122)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000102#endif
103#ifndef BLKPBSZGET
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300104# define BLKPBSZGET _IO(0x12,123)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000105#endif
106#ifndef BLKDISCARDZEROES
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300107# define BLKDISCARDZEROES _IO(0x12,124)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000108#endif
109#ifndef BLKSECDISCARD
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300110# 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)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000117#endif
118
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000119#include "xlat/blkpg_ops.h"
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000120
121static void
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +0000122print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000123{
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +0000124 struct_blkpg_partition p;
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000125
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200126 tprints("{");
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000127 printxval(blkpg_ops, blkpg->op, "BLKPG_???");
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000128
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300129 tprintf(", flags=%d, datalen=%d, data=",
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000130 blkpg->flags, blkpg->datalen);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000131
Elliott Hughesd35df492017-02-15 15:19:05 -0800132 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);
Dmitry V. Levin0a870582015-01-25 01:04:01 +0000136 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);
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300141 tprints("}");
Dmitry V. Levin0a870582015-01-25 01:04:01 +0000142 }
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300143 tprints("}");
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000144}
145
Elliott Hughesd35df492017-02-15 15:19:05 -0800146MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
147 const unsigned int code, const kernel_ulong_t arg)
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000148{
149 switch (code) {
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000150 /* take arg as a value, not as a pointer */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000151 case BLKRASET:
152 case BLKFRASET:
Elliott Hughesd35df492017-02-15 15:19:05 -0800153 tprintf(", %" PRI_klu, arg);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000154 break;
155
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300156 /* return an unsigned short */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000157 case BLKSECTGET:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300158 case BLKROTATIONAL:
159 if (entering(tcp))
160 return 0;
161 tprints(", ");
162 printnum_short(tcp, arg, "%hu");
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000163 break;
164
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000165 /* return a signed int */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000166 case BLKROGET:
167 case BLKBSZGET:
168 case BLKSSZGET:
169 case BLKALIGNOFF:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300170 if (entering(tcp))
171 return 0;
Dmitry V. Levin0c9087c2016-05-26 12:36:56 +0000172 /* fall through */
173 /* take a signed int */
174 case BLKROSET:
175 case BLKBSZSET:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300176 tprints(", ");
177 printnum_int(tcp, arg, "%d");
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000178 break;
179
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000180 /* return an unsigned int */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000181 case BLKPBSZGET:
182 case BLKIOMIN:
183 case BLKIOOPT:
184 case BLKDISCARDZEROES:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300185 if (entering(tcp))
186 return 0;
187 tprints(", ");
188 printnum_int(tcp, arg, "%u");
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000189 break;
190
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000191 /* return a signed long */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000192 case BLKRAGET:
193 case BLKFRAGET:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300194 if (entering(tcp))
195 return 0;
196 tprints(", ");
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000197 printnum_slong(tcp, arg);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000198 break;
199
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000200 /* returns an unsigned long */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000201 case BLKGETSIZE:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300202 if (entering(tcp))
203 return 0;
204 tprints(", ");
Dmitry V. Levin2479ef02015-08-18 14:58:27 +0000205 printnum_ulong(tcp, arg);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000206 break;
207
Dmitry V. Levin25caa312011-08-16 21:36:16 +0000208#ifdef HAVE_BLKGETSIZE64
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300209 /* returns an uint64_t */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000210 case BLKGETSIZE64:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300211 if (entering(tcp))
212 return 0;
213 tprints(", ");
214 printnum_int64(tcp, arg, "%" PRIu64);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000215 break;
Denys Vlasenko5bd67c82011-08-15 11:36:09 +0200216#endif
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000217
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300218 /* takes a pair of uint64_t */
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000219 case BLKDISCARD:
220 case BLKSECDISCARD:
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300221 case BLKZEROOUT:
222 tprints(", ");
Dmitry V. Levin46d25c22016-05-26 12:33:21 +0000223 printpair_int64(tcp, arg, "%" PRIu64);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000224 break;
225
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300226 /* More complex types */
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300227 case BLKPG: {
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +0000228 struct_blkpg_ioctl_arg blkpg;
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300229
230 tprints(", ");
231 if (!umove_or_printaddr(tcp, arg, &blkpg))
232 print_blkpg_req(tcp, &blkpg);
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000233 break;
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300234 }
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000235
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000236 case BLKTRACESETUP:
237 if (entering(tcp)) {
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +0000238 struct_blk_user_trace_setup buts;
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300239
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 {
Dmitry V. Levin37d1b3d2016-05-26 10:43:51 +0000251 struct_blk_user_trace_setup buts;
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300252
Dmitry V. Levin0bea5282016-05-26 10:04:39 +0000253 if (!syserror(tcp) && !umove(tcp, arg, &buts)) {
254 tprints(", name=");
255 print_quoted_string(buts.name, sizeof(buts.name),
256 QUOTE_0_TERMINATED);
Dmitry V. Levin0a870582015-01-25 01:04:01 +0000257 }
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300258 tprints("}");
259 break;
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000260 }
Dmitry V. Levinbe284ca2011-01-16 23:07:51 +0000261
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300262 /* No arguments */
263 case BLKRRPART:
264 case BLKFLSBUF:
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000265 case BLKTRACESTART:
266 case BLKTRACESTOP:
267 case BLKTRACETEARDOWN:
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000268 break;
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300269 default:
270 return RVAL_DECODED;
271 }
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000272
Dmitry V. Levina0beac12015-07-05 15:15:03 +0300273 return RVAL_DECODED | 1;
Dmitry V. Levin4ef6db42011-01-15 20:15:31 +0000274}