]> granicus.if.org Git - strace/blob - block.c
nlattr: add unsigned int decoders that print in hex form
[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  * Copyright (c) 2011-2018 The strace developers.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "defs.h"
31
32 #include DEF_MPERS_TYPE(struct_blk_user_trace_setup)
33 #include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg)
34 #include DEF_MPERS_TYPE(struct_blkpg_partition)
35
36 #include <linux/ioctl.h>
37 #include <linux/fs.h>
38
39 typedef struct {
40         int op;
41         int flags;
42         int datalen;
43         void *data;
44 } struct_blkpg_ioctl_arg;
45
46 #define BLKPG_DEVNAMELTH        64
47 #define BLKPG_VOLNAMELTH        64
48 typedef struct {
49         int64_t start;                  /* starting offset in bytes */
50         int64_t length;                 /* length in bytes */
51         int pno;                        /* partition number */
52         char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
53                                            to be used in kernel messages */
54         char volname[BLKPG_VOLNAMELTH]; /* volume label */
55 } struct_blkpg_partition;
56
57 #define BLKTRACE_BDEV_SIZE      32
58 typedef struct blk_user_trace_setup {
59         char name[BLKTRACE_BDEV_SIZE];  /* output */
60         uint16_t act_mask;              /* input */
61         uint32_t buf_size;              /* input */
62         uint32_t buf_nr;                /* input */
63         uint64_t start_lba;
64         uint64_t end_lba;
65         uint32_t pid;
66 } struct_blk_user_trace_setup;
67
68 #include MPERS_DEFS
69
70 #include "print_fields.h"
71
72 #ifndef BLKPG
73 # define BLKPG      _IO(0x12, 105)
74 #endif
75
76 /*
77  * ioctl numbers <= 114 are present in Linux 2.4.  The following ones have been
78  * added since then and headers containing them may not be available on every
79  * system.
80  */
81
82 #ifndef BLKTRACESETUP
83 # define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup)
84 #endif
85 #ifndef BLKTRACESTART
86 # define BLKTRACESTART _IO(0x12, 116)
87 #endif
88 #ifndef BLKTRACESTOP
89 # define BLKTRACESTOP _IO(0x12, 117)
90 #endif
91 #ifndef BLKTRACETEARDOWN
92 # define BLKTRACETEARDOWN _IO(0x12, 118)
93 #endif
94 #ifndef BLKDISCARD
95 # define BLKDISCARD _IO(0x12, 119)
96 #endif
97 #ifndef BLKIOMIN
98 # define BLKIOMIN _IO(0x12, 120)
99 #endif
100 #ifndef BLKIOOPT
101 # define BLKIOOPT _IO(0x12, 121)
102 #endif
103 #ifndef BLKALIGNOFF
104 # define BLKALIGNOFF _IO(0x12, 122)
105 #endif
106 #ifndef BLKPBSZGET
107 # define BLKPBSZGET _IO(0x12, 123)
108 #endif
109 #ifndef BLKDISCARDZEROES
110 # define BLKDISCARDZEROES _IO(0x12, 124)
111 #endif
112 #ifndef BLKSECDISCARD
113 # define BLKSECDISCARD _IO(0x12, 125)
114 #endif
115 #ifndef BLKROTATIONAL
116 # define BLKROTATIONAL _IO(0x12, 126)
117 #endif
118 #ifndef BLKZEROOUT
119 # define BLKZEROOUT _IO(0x12, 127)
120 #endif
121
122 #include "xlat/blkpg_ops.h"
123
124 static void
125 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
126 {
127         struct_blkpg_partition p;
128
129         PRINT_FIELD_XVAL("{", *blkpg, op, blkpg_ops, "BLKPG_???");
130         PRINT_FIELD_D(", ", *blkpg, flags);
131         PRINT_FIELD_D(", ", *blkpg, datalen);
132
133         tprints(", data=");
134         if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) {
135                 PRINT_FIELD_D("{", p, start);
136                 PRINT_FIELD_D(", ", p, length);
137                 PRINT_FIELD_D(", ", p, pno);
138                 PRINT_FIELD_CSTRING(", ", p, devname);
139                 PRINT_FIELD_CSTRING(", ", p, volname);
140                 tprints("}");
141         }
142         tprints("}");
143 }
144
145 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
146                    const unsigned int code, const kernel_ulong_t arg)
147 {
148         switch (code) {
149         /* take arg as a value, not as a pointer */
150         case BLKRASET:
151         case BLKFRASET:
152                 tprintf(", %" PRI_klu, arg);
153                 break;
154
155         /* return an unsigned short */
156         case BLKSECTGET:
157         case BLKROTATIONAL:
158                 if (entering(tcp))
159                         return 0;
160                 tprints(", ");
161                 printnum_short(tcp, arg, "%hu");
162                 break;
163
164         /* return a signed int */
165         case BLKROGET:
166         case BLKBSZGET:
167         case BLKSSZGET:
168         case BLKALIGNOFF:
169                 if (entering(tcp))
170                         return 0;
171                 ATTRIBUTE_FALLTHROUGH;
172         /* take a signed int */
173         case BLKROSET:
174         case BLKBSZSET:
175                 tprints(", ");
176                 printnum_int(tcp, arg, "%d");
177                 break;
178
179         /* return an unsigned int */
180         case BLKPBSZGET:
181         case BLKIOMIN:
182         case BLKIOOPT:
183         case BLKDISCARDZEROES:
184                 if (entering(tcp))
185                         return 0;
186                 tprints(", ");
187                 printnum_int(tcp, arg, "%u");
188                 break;
189
190         /* return a signed long */
191         case BLKRAGET:
192         case BLKFRAGET:
193                 if (entering(tcp))
194                         return 0;
195                 tprints(", ");
196                 printnum_slong(tcp, arg);
197                 break;
198
199         /* returns an unsigned long */
200         case BLKGETSIZE:
201                 if (entering(tcp))
202                         return 0;
203                 tprints(", ");
204                 printnum_ulong(tcp, arg);
205                 break;
206
207 #ifdef HAVE_BLKGETSIZE64
208         /* returns an uint64_t */
209         case BLKGETSIZE64:
210                 if (entering(tcp))
211                         return 0;
212                 tprints(", ");
213                 printnum_int64(tcp, arg, "%" PRIu64);
214                 break;
215 #endif
216
217         /* takes a pair of uint64_t */
218         case BLKDISCARD:
219         case BLKSECDISCARD:
220         case BLKZEROOUT:
221                 tprints(", ");
222                 printpair_int64(tcp, arg, "%" PRIu64);
223                 break;
224
225         /* More complex types */
226         case BLKPG: {
227                 struct_blkpg_ioctl_arg blkpg;
228
229                 tprints(", ");
230                 if (!umove_or_printaddr(tcp, arg, &blkpg))
231                         print_blkpg_req(tcp, &blkpg);
232                 break;
233         }
234
235         case BLKTRACESETUP:
236                 if (entering(tcp)) {
237                         struct_blk_user_trace_setup buts;
238
239                         tprints(", ");
240                         if (umove_or_printaddr(tcp, arg, &buts))
241                                 break;
242                         PRINT_FIELD_U("{", buts, act_mask);
243                         PRINT_FIELD_U(", ", buts, buf_size);
244                         PRINT_FIELD_U(", ", buts, buf_nr);
245                         PRINT_FIELD_U(", ", buts, start_lba);
246                         PRINT_FIELD_U(", ", buts, end_lba);
247                         PRINT_FIELD_U(", ", buts, pid);
248                         return 0;
249                 } else {
250                         struct_blk_user_trace_setup buts;
251
252                         if (!syserror(tcp) && !umove(tcp, arg, &buts))
253                                 PRINT_FIELD_CSTRING(", ", buts, name);
254                         tprints("}");
255                         break;
256                 }
257
258         /* No arguments */
259         case BLKRRPART:
260         case BLKFLSBUF:
261         case BLKTRACESTART:
262         case BLKTRACESTOP:
263         case BLKTRACETEARDOWN:
264                 break;
265         default:
266                 return RVAL_DECODED;
267         }
268
269         return RVAL_IOCTL_DECODED;
270 }