]> granicus.if.org Git - strace/blob - block.c
Introduce generic STRINGIFY and STRINGIFY_VAL macros
[strace] / block.c
1 /*
2  * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
3  * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@altlinux.org>
4  * 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"
30
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
35 #include <linux/ioctl.h>
36 #include <linux/fs.h>
37
38 typedef 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
47 typedef 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
56 #define BLKTRACE_BDEV_SIZE      32
57 typedef struct blk_user_trace_setup {
58         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;
65 } struct_blk_user_trace_setup;
66
67 #include MPERS_DEFS
68
69 #ifndef BLKPG
70 # define BLKPG      _IO(0x12, 105)
71 #endif
72
73 /*
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  */
78
79 #ifndef BLKTRACESETUP
80 # define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup)
81 #endif
82 #ifndef BLKTRACESTART
83 # define BLKTRACESTART _IO(0x12, 116)
84 #endif
85 #ifndef BLKTRACESTOP
86 # define BLKTRACESTOP _IO(0x12, 117)
87 #endif
88 #ifndef BLKTRACETEARDOWN
89 # define BLKTRACETEARDOWN _IO(0x12, 118)
90 #endif
91 #ifndef BLKDISCARD
92 # define BLKDISCARD _IO(0x12, 119)
93 #endif
94 #ifndef BLKIOMIN
95 # define BLKIOMIN _IO(0x12, 120)
96 #endif
97 #ifndef BLKIOOPT
98 # define BLKIOOPT _IO(0x12, 121)
99 #endif
100 #ifndef BLKALIGNOFF
101 # define BLKALIGNOFF _IO(0x12, 122)
102 #endif
103 #ifndef BLKPBSZGET
104 # define BLKPBSZGET _IO(0x12, 123)
105 #endif
106 #ifndef BLKDISCARDZEROES
107 # define BLKDISCARDZEROES _IO(0x12, 124)
108 #endif
109 #ifndef BLKSECDISCARD
110 # 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)
117 #endif
118
119 #include "xlat/blkpg_ops.h"
120
121 static void
122 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
123 {
124         struct_blkpg_partition p;
125
126         tprints("{");
127         printxval(blkpg_ops, blkpg->op, "BLKPG_???");
128
129         tprintf(", flags=%d, datalen=%d, data=",
130                 blkpg->flags, blkpg->datalen);
131
132         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);
136                 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);
141                 tprints("}");
142         }
143         tprints("}");
144 }
145
146 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
147                    const unsigned int code, const kernel_ulong_t arg)
148 {
149         switch (code) {
150         /* take arg as a value, not as a pointer */
151         case BLKRASET:
152         case BLKFRASET:
153                 tprintf(", %" PRI_klu, arg);
154                 break;
155
156         /* return an unsigned short */
157         case BLKSECTGET:
158         case BLKROTATIONAL:
159                 if (entering(tcp))
160                         return 0;
161                 tprints(", ");
162                 printnum_short(tcp, arg, "%hu");
163                 break;
164
165         /* return a signed int */
166         case BLKROGET:
167         case BLKBSZGET:
168         case BLKSSZGET:
169         case BLKALIGNOFF:
170                 if (entering(tcp))
171                         return 0;
172                 /* fall through */
173         /* take a signed int */
174         case BLKROSET:
175         case BLKBSZSET:
176                 tprints(", ");
177                 printnum_int(tcp, arg, "%d");
178                 break;
179
180         /* return an unsigned int */
181         case BLKPBSZGET:
182         case BLKIOMIN:
183         case BLKIOOPT:
184         case BLKDISCARDZEROES:
185                 if (entering(tcp))
186                         return 0;
187                 tprints(", ");
188                 printnum_int(tcp, arg, "%u");
189                 break;
190
191         /* return a signed long */
192         case BLKRAGET:
193         case BLKFRAGET:
194                 if (entering(tcp))
195                         return 0;
196                 tprints(", ");
197                 printnum_slong(tcp, arg);
198                 break;
199
200         /* returns an unsigned long */
201         case BLKGETSIZE:
202                 if (entering(tcp))
203                         return 0;
204                 tprints(", ");
205                 printnum_ulong(tcp, arg);
206                 break;
207
208 #ifdef HAVE_BLKGETSIZE64
209         /* returns an uint64_t */
210         case BLKGETSIZE64:
211                 if (entering(tcp))
212                         return 0;
213                 tprints(", ");
214                 printnum_int64(tcp, arg, "%" PRIu64);
215                 break;
216 #endif
217
218         /* takes a pair of uint64_t */
219         case BLKDISCARD:
220         case BLKSECDISCARD:
221         case BLKZEROOUT:
222                 tprints(", ");
223                 printpair_int64(tcp, arg, "%" PRIu64);
224                 break;
225
226         /* More complex types */
227         case BLKPG: {
228                 struct_blkpg_ioctl_arg blkpg;
229
230                 tprints(", ");
231                 if (!umove_or_printaddr(tcp, arg, &blkpg))
232                         print_blkpg_req(tcp, &blkpg);
233                 break;
234         }
235
236         case BLKTRACESETUP:
237                 if (entering(tcp)) {
238                         struct_blk_user_trace_setup buts;
239
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 {
251                         struct_blk_user_trace_setup buts;
252
253                         if (!syserror(tcp) && !umove(tcp, arg, &buts)) {
254                                 tprints(", name=");
255                                 print_quoted_string(buts.name, sizeof(buts.name),
256                                                     QUOTE_0_TERMINATED);
257                         }
258                         tprints("}");
259                         break;
260                 }
261
262         /* No arguments */
263         case BLKRRPART:
264         case BLKFLSBUF:
265         case BLKTRACESTART:
266         case BLKTRACESTOP:
267         case BLKTRACETEARDOWN:
268                 break;
269         default:
270                 return RVAL_DECODED;
271         }
272
273         return RVAL_DECODED | 1;
274 }