]> granicus.if.org Git - strace/blob - block.c
Update debian/watch
[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  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11
12 #include DEF_MPERS_TYPE(struct_blk_user_trace_setup)
13 #include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg)
14 #include DEF_MPERS_TYPE(struct_blkpg_partition)
15
16 #include <linux/ioctl.h>
17 #include <linux/fs.h>
18
19 typedef struct {
20         int op;
21         int flags;
22         int datalen;
23         void *data;
24 } struct_blkpg_ioctl_arg;
25
26 #define BLKPG_DEVNAMELTH        64
27 #define BLKPG_VOLNAMELTH        64
28 typedef struct {
29         int64_t start;                  /* starting offset in bytes */
30         int64_t length;                 /* length in bytes */
31         int pno;                        /* partition number */
32         char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
33                                            to be used in kernel messages */
34         char volname[BLKPG_VOLNAMELTH]; /* volume label */
35 } struct_blkpg_partition;
36
37 #define BLKTRACE_BDEV_SIZE      32
38 typedef struct blk_user_trace_setup {
39         char name[BLKTRACE_BDEV_SIZE];  /* output */
40         uint16_t act_mask;              /* input */
41         uint32_t buf_size;              /* input */
42         uint32_t buf_nr;                /* input */
43         uint64_t start_lba;
44         uint64_t end_lba;
45         uint32_t pid;
46 } struct_blk_user_trace_setup;
47
48 /* Provide fall-back definitions for BLK* ioctls */
49 #define XLAT_MACROS_ONLY
50 #include "xlat/block_ioctl_cmds.h"
51 #undef XLAT_MACROS_ONLY
52
53 #include MPERS_DEFS
54
55 #include "print_fields.h"
56
57 #include "xlat/blkpg_ops.h"
58
59 static void
60 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
61 {
62         struct_blkpg_partition p;
63
64         PRINT_FIELD_XVAL("{", *blkpg, op, blkpg_ops, "BLKPG_???");
65         PRINT_FIELD_D(", ", *blkpg, flags);
66         PRINT_FIELD_D(", ", *blkpg, datalen);
67
68         tprints(", data=");
69         if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) {
70                 PRINT_FIELD_D("{", p, start);
71                 PRINT_FIELD_D(", ", p, length);
72                 PRINT_FIELD_D(", ", p, pno);
73                 PRINT_FIELD_CSTRING(", ", p, devname);
74                 PRINT_FIELD_CSTRING(", ", p, volname);
75                 tprints("}");
76         }
77         tprints("}");
78 }
79
80 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
81                    const unsigned int code, const kernel_ulong_t arg)
82 {
83         switch (code) {
84         /* take arg as a value, not as a pointer */
85         case BLKRASET:
86         case BLKFRASET:
87                 tprintf(", %" PRI_klu, arg);
88                 break;
89
90         /* return an unsigned short */
91         case BLKSECTGET:
92         case BLKROTATIONAL:
93                 if (entering(tcp))
94                         return 0;
95                 tprints(", ");
96                 printnum_short(tcp, arg, "%hu");
97                 break;
98
99         /* return a signed int */
100         case BLKROGET:
101         case BLKBSZGET:
102         case BLKSSZGET:
103         case BLKALIGNOFF:
104                 if (entering(tcp))
105                         return 0;
106                 ATTRIBUTE_FALLTHROUGH;
107         /* take a signed int */
108         case BLKROSET:
109         case BLKBSZSET:
110                 tprints(", ");
111                 printnum_int(tcp, arg, "%d");
112                 break;
113
114         /* return an unsigned int */
115         case BLKPBSZGET:
116         case BLKIOMIN:
117         case BLKIOOPT:
118         case BLKDISCARDZEROES:
119         case BLKGETZONESZ:
120         case BLKGETNRZONES:
121                 if (entering(tcp))
122                         return 0;
123                 tprints(", ");
124                 printnum_int(tcp, arg, "%u");
125                 break;
126
127         /* return a signed long */
128         case BLKRAGET:
129         case BLKFRAGET:
130                 if (entering(tcp))
131                         return 0;
132                 tprints(", ");
133                 printnum_slong(tcp, arg);
134                 break;
135
136         /* returns an unsigned long */
137         case BLKGETSIZE:
138                 if (entering(tcp))
139                         return 0;
140                 tprints(", ");
141                 printnum_ulong(tcp, arg);
142                 break;
143
144         /* returns an uint64_t */
145         case BLKGETSIZE64:
146                 if (entering(tcp))
147                         return 0;
148                 tprints(", ");
149                 printnum_int64(tcp, arg, "%" PRIu64);
150                 break;
151
152         /* takes a pair of uint64_t */
153         case BLKDISCARD:
154         case BLKSECDISCARD:
155         case BLKZEROOUT:
156                 tprints(", ");
157                 printpair_int64(tcp, arg, "%" PRIu64);
158                 break;
159
160         /* More complex types */
161         case BLKPG: {
162                 struct_blkpg_ioctl_arg blkpg;
163
164                 tprints(", ");
165                 if (!umove_or_printaddr(tcp, arg, &blkpg))
166                         print_blkpg_req(tcp, &blkpg);
167                 break;
168         }
169
170         case BLKTRACESETUP:
171                 if (entering(tcp)) {
172                         struct_blk_user_trace_setup buts;
173
174                         tprints(", ");
175                         if (umove_or_printaddr(tcp, arg, &buts))
176                                 break;
177                         PRINT_FIELD_U("{", buts, act_mask);
178                         PRINT_FIELD_U(", ", buts, buf_size);
179                         PRINT_FIELD_U(", ", buts, buf_nr);
180                         PRINT_FIELD_U(", ", buts, start_lba);
181                         PRINT_FIELD_U(", ", buts, end_lba);
182                         PRINT_FIELD_U(", ", buts, pid);
183                         return 0;
184                 } else {
185                         struct_blk_user_trace_setup buts;
186
187                         if (!syserror(tcp) && !umove(tcp, arg, &buts))
188                                 PRINT_FIELD_CSTRING(", ", buts, name);
189                         tprints("}");
190                         break;
191                 }
192
193         /* No arguments */
194         case BLKRRPART:
195         case BLKFLSBUF:
196         case BLKTRACESTART:
197         case BLKTRACESTOP:
198         case BLKTRACETEARDOWN:
199                 break;
200         default:
201                 return RVAL_DECODED;
202         }
203
204         return RVAL_IOCTL_DECODED;
205 }