]> granicus.if.org Git - strace/blob - block.c
Print struct iovec as a regular structure
[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/blkpg.h>
36 #include <linux/fs.h>
37
38 #define BLKTRACE_BDEV_SIZE      32
39 typedef struct blk_user_trace_setup {
40         char name[BLKTRACE_BDEV_SIZE];  /* output */
41         uint16_t act_mask;              /* input */
42         uint32_t buf_size;              /* input */
43         uint32_t buf_nr;                /* input */
44         uint64_t start_lba;
45         uint64_t end_lba;
46         uint32_t pid;
47 } struct_blk_user_trace_setup;
48
49 typedef struct blkpg_ioctl_arg struct_blkpg_ioctl_arg;
50 typedef struct blkpg_partition struct_blkpg_partition;
51
52 #include MPERS_DEFS
53
54 /*
55  * ioctl numbers <= 114 are present in Linux 2.4.  The following ones have been
56  * added since then and headers containing them may not be available on every
57  * system.
58  */
59
60 #ifndef BLKTRACESETUP
61 # define BLKTRACESETUP _IOWR(0x12, 115, struct_blk_user_trace_setup)
62 #endif
63 #ifndef BLKTRACESTART
64 # define BLKTRACESTART _IO(0x12,116)
65 #endif
66 #ifndef BLKTRACESTOP
67 # define BLKTRACESTOP _IO(0x12,117)
68 #endif
69 #ifndef BLKTRACETEARDOWN
70 # define BLKTRACETEARDOWN _IO(0x12,118)
71 #endif
72 #ifndef BLKDISCARD
73 # define BLKDISCARD _IO(0x12,119)
74 #endif
75 #ifndef BLKIOMIN
76 # define BLKIOMIN _IO(0x12,120)
77 #endif
78 #ifndef BLKIOOPT
79 # define BLKIOOPT _IO(0x12,121)
80 #endif
81 #ifndef BLKALIGNOFF
82 # define BLKALIGNOFF _IO(0x12,122)
83 #endif
84 #ifndef BLKPBSZGET
85 # define BLKPBSZGET _IO(0x12,123)
86 #endif
87 #ifndef BLKDISCARDZEROES
88 # define BLKDISCARDZEROES _IO(0x12,124)
89 #endif
90 #ifndef BLKSECDISCARD
91 # define BLKSECDISCARD _IO(0x12,125)
92 #endif
93 #ifndef BLKROTATIONAL
94 # define BLKROTATIONAL _IO(0x12,126)
95 #endif
96 #ifndef BLKZEROOUT
97 # define BLKZEROOUT _IO(0x12,127)
98 #endif
99
100 #include "xlat/blkpg_ops.h"
101
102 static void
103 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
104 {
105         struct_blkpg_partition p;
106
107         tprints("{");
108         printxval(blkpg_ops, blkpg->op, "BLKPG_???");
109
110         tprintf(", flags=%d, datalen=%d, data=",
111                 blkpg->flags, blkpg->datalen);
112
113         if (!umove_or_printaddr(tcp, (long) blkpg->data, &p)) {
114                 tprintf("{start=%lld, length=%lld, pno=%d, devname=",
115                         (long long) p.start, (long long) p.length, p.pno);
116                 print_quoted_string(p.devname, sizeof(p.devname),
117                                     QUOTE_0_TERMINATED);
118                 tprints(", volname=");
119                 print_quoted_string(p.volname, sizeof(p.volname),
120                                     QUOTE_0_TERMINATED);
121                 tprints("}");
122         }
123         tprints("}");
124 }
125
126 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *tcp,
127                    const unsigned int code, const long arg)
128 {
129         switch (code) {
130         /* take arg as a value, not as a pointer */
131         case BLKRASET:
132         case BLKFRASET:
133                 tprintf(", %lu", arg);
134                 break;
135
136         /* return an unsigned short */
137         case BLKSECTGET:
138         case BLKROTATIONAL:
139                 if (entering(tcp))
140                         return 0;
141                 tprints(", ");
142                 printnum_short(tcp, arg, "%hu");
143                 break;
144
145         /* return a signed int */
146         case BLKROGET:
147         case BLKBSZGET:
148         case BLKSSZGET:
149         case BLKALIGNOFF:
150                 if (entering(tcp))
151                         return 0;
152                 /* fall through */
153         /* take a signed int */
154         case BLKROSET:
155         case BLKBSZSET:
156                 tprints(", ");
157                 printnum_int(tcp, arg, "%d");
158                 break;
159
160         /* return an unsigned int */
161         case BLKPBSZGET:
162         case BLKIOMIN:
163         case BLKIOOPT:
164         case BLKDISCARDZEROES:
165                 if (entering(tcp))
166                         return 0;
167                 tprints(", ");
168                 printnum_int(tcp, arg, "%u");
169                 break;
170
171         /* return a signed long */
172         case BLKRAGET:
173         case BLKFRAGET:
174                 if (entering(tcp))
175                         return 0;
176                 tprints(", ");
177                 printnum_slong(tcp, arg);
178                 break;
179
180         /* returns an unsigned long */
181         case BLKGETSIZE:
182                 if (entering(tcp))
183                         return 0;
184                 tprints(", ");
185                 printnum_ulong(tcp, arg);
186                 break;
187
188 #ifdef HAVE_BLKGETSIZE64
189         /* returns an uint64_t */
190         case BLKGETSIZE64:
191                 if (entering(tcp))
192                         return 0;
193                 tprints(", ");
194                 printnum_int64(tcp, arg, "%" PRIu64);
195                 break;
196 #endif
197
198         /* takes a pair of uint64_t */
199         case BLKDISCARD:
200         case BLKSECDISCARD:
201         case BLKZEROOUT:
202                 tprints(", ");
203                 printpair_int64(tcp, arg, "%" PRIu64);
204                 break;
205
206         /* More complex types */
207         case BLKPG: {
208                 struct_blkpg_ioctl_arg blkpg;
209
210                 tprints(", ");
211                 if (!umove_or_printaddr(tcp, arg, &blkpg))
212                         print_blkpg_req(tcp, &blkpg);
213                 break;
214         }
215
216         case BLKTRACESETUP:
217                 if (entering(tcp)) {
218                         struct_blk_user_trace_setup buts;
219
220                         tprints(", ");
221                         if (umove_or_printaddr(tcp, arg, &buts))
222                                 break;
223                         tprintf("{act_mask=%u, buf_size=%u, "
224                                 "buf_nr=%u, start_lba=%" PRIu64 ", "
225                                 "end_lba=%" PRIu64 ", pid=%u",
226                                 (unsigned)buts.act_mask, buts.buf_size,
227                                 buts.buf_nr, buts.start_lba,
228                                 buts.end_lba, buts.pid);
229                         return 1;
230                 } else {
231                         struct_blk_user_trace_setup buts;
232
233                         if (!syserror(tcp) && !umove(tcp, arg, &buts)) {
234                                 tprints(", name=");
235                                 print_quoted_string(buts.name, sizeof(buts.name),
236                                                     QUOTE_0_TERMINATED);
237                         }
238                         tprints("}");
239                         break;
240                 }
241
242         /* No arguments */
243         case BLKRRPART:
244         case BLKFLSBUF:
245         case BLKTRACESTART:
246         case BLKTRACESTOP:
247         case BLKTRACETEARDOWN:
248                 break;
249         default:
250                 return RVAL_DECODED;
251         }
252
253         return RVAL_DECODED | 1;
254 }