3 #ifdef HAVE_LINUX_DM_IOCTL_H
5 # include <linux/dm-ioctl.h>
6 # include <linux/ioctl.h>
8 # include <sys/sysmacros.h>
10 # if DM_VERSION_MAJOR == 4
12 /* Definitions for command which have been added later */
14 # ifndef DM_LIST_VERSIONS
15 # define DM_LIST_VERSIONS _IOWR(DM_IOCTL, 0xd, struct dm_ioctl)
17 # ifndef DM_TARGET_MSG
18 # define DM_TARGET_MSG _IOWR(DM_IOCTL, 0xe, struct dm_ioctl)
20 # ifndef DM_DEV_SET_GEOMETRY
21 # define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, 0xf, struct dm_ioctl)
26 dm_decode_device(const unsigned int code, const struct dm_ioctl *ioc)
31 case DM_LIST_VERSIONS:
35 tprintf(", dev=makedev(%u, %u)",
36 major(ioc->dev), minor(ioc->dev));
39 print_quoted_string(ioc->name, DM_NAME_LEN,
44 print_quoted_string(ioc->uuid, DM_UUID_LEN,
52 dm_decode_values(struct tcb *tcp, const unsigned int code,
53 const struct dm_ioctl *ioc)
58 tprintf(", target_count=%" PRIu32,
62 if (ioc->flags & DM_SUSPEND_FLAG)
68 tprintf(", event_nr=%" PRIu32,
72 } else if (!syserror(tcp)) {
84 tprintf(", target_count=%" PRIu32,
86 tprintf(", open_count=%" PRIu32,
88 tprintf(", event_nr=%" PRIu32,
95 #include "xlat/dm_flags.h"
98 dm_decode_flags(const struct dm_ioctl *ioc)
101 printflags(dm_flags, ioc->flags, "DM_???");
105 dm_decode_dm_target_spec(struct tcb *const tcp, const kernel_ulong_t addr,
106 const struct dm_ioctl *const ioc)
108 static const uint32_t target_spec_size =
109 sizeof(struct dm_target_spec);
111 uint32_t offset = ioc->data_start;
115 if (ioc->target_count)
121 for (i = 0; i < ioc->target_count; i++) {
122 struct dm_target_spec s;
124 offset_end = offset + target_spec_size;
126 if (offset_end <= offset || offset_end > ioc->data_size)
131 if (i >= max_strlen) {
136 if (umove_or_printaddr(tcp, addr + offset, &s))
139 tprintf("{sector_start=%" PRI__u64 ", length=%" PRI__u64,
140 s.sector_start, s.length);
143 tprintf(", status=%" PRId32, s.status);
145 tprints(", target_type=");
146 print_quoted_string(s.target_type, DM_MAX_TYPE_NAME,
149 tprints(", string=");
150 printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end,
157 offset = ioc->data_start + s.next;
159 if (offset <= offset_end)
166 tprints(", /* misplaced struct dm_target_spec */ ...");
170 dm_print_dev(struct tcb *tcp, void *dev_ptr, size_t dev_size, void *dummy)
172 uint64_t *dev = (uint64_t *) dev_ptr;
174 tprintf("makedev(%u, %u)", major(*dev), minor(*dev));
180 dm_decode_dm_target_deps(struct tcb *const tcp, const kernel_ulong_t addr,
181 const struct dm_ioctl *const ioc)
183 static const uint32_t target_deps_dev_offs =
184 offsetof(struct dm_target_deps, dev);
186 struct dm_target_deps s;
187 uint32_t offset = ioc->data_start;
188 uint32_t offset_end = offset + target_deps_dev_offs;
198 if (offset_end <= offset || offset_end > ioc->data_size)
201 if (umove_or_printaddr(tcp, addr + offset, &s))
204 space = (ioc->data_size - offset_end) / sizeof(dev_buf);
209 tprintf("{count=%u, deps=", s.count);
211 print_array(tcp, addr + offset_end, s.count, &dev_buf, sizeof(dev_buf),
212 umoven_or_printaddr, dm_print_dev, NULL);
219 tprints("/* misplaced struct dm_target_deps */ ...");
223 dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr,
224 const struct dm_ioctl *const ioc)
226 static const uint32_t name_list_name_offs =
227 offsetof(struct dm_name_list, name);
228 struct dm_name_list s;
229 uint32_t offset = ioc->data_start;
238 for (count = 0;; count++) {
239 offset_end = offset + name_list_name_offs;
241 if (offset_end <= offset || offset_end > ioc->data_size)
246 if (count >= max_strlen) {
251 if (umove_or_printaddr(tcp, addr + offset, &s))
253 if (!count && !s.dev) {
254 tprints("/* no devices present */");
258 tprintf("{dev=makedev(%u, %u), name=", major(s.dev),
260 printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end,
268 if (offset <= offset_end)
275 tprints(", /* misplaced struct dm_name_list */ ...");
279 dm_decode_dm_target_versions(struct tcb *const tcp, const kernel_ulong_t addr,
280 const struct dm_ioctl *const ioc)
282 static const uint32_t target_vers_name_offs =
283 offsetof(struct dm_target_versions, name);
284 struct dm_target_versions s;
285 uint32_t offset = ioc->data_start;
294 for (count = 0;; count++) {
295 offset_end = offset + target_vers_name_offs;
297 if (offset_end <= offset || offset_end > ioc->data_size)
302 if (count >= max_strlen) {
307 if (umove_or_printaddr(tcp, addr + offset, &s))
311 printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end,
313 tprintf(", version=%" PRIu32 ".%" PRIu32 ".%" PRIu32 "}",
314 s.version[0], s.version[1], s.version[2]);
320 if (offset <= offset_end)
327 tprints(", /* misplaced struct dm_target_versions */ ...");
331 dm_decode_dm_target_msg(struct tcb *const tcp, const kernel_ulong_t addr,
332 const struct dm_ioctl *const ioc)
334 static const uint32_t target_msg_message_offs =
335 offsetof(struct dm_target_msg, message);
336 uint32_t offset = ioc->data_start;
337 uint32_t offset_end = offset + target_msg_message_offs;
344 if (offset_end > offset && offset_end <= ioc->data_size) {
345 struct dm_target_msg s;
349 if (umove_or_printaddr(tcp, addr + offset, &s))
352 tprintf("{sector=%" PRI__u64 ", message=", s.sector);
353 printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end,
357 tprints(", /* misplaced struct dm_target_msg */");
362 dm_decode_string(struct tcb *const tcp, const kernel_ulong_t addr,
363 const struct dm_ioctl *const ioc)
365 uint32_t offset = ioc->data_start;
372 if (offset < ioc->data_size) {
373 tprints(", string=");
374 printstr_ex(tcp, addr + offset, ioc->data_size - offset,
377 tprints(", /* misplaced string */");
382 dm_ioctl_has_params(const unsigned int code)
399 dm_known_ioctl(struct tcb *const tcp, const unsigned int code,
400 const kernel_ulong_t arg)
402 struct dm_ioctl *ioc = NULL;
403 struct dm_ioctl *entering_ioc = NULL;
404 bool ioc_changed = false;
407 ioc = malloc(sizeof(*ioc));
411 ioc = alloca(sizeof(*ioc));
414 if ((umoven(tcp, arg, offsetof(struct dm_ioctl, data), ioc) < 0) ||
415 (ioc->data_size < offsetof(struct dm_ioctl, data_size))) {
421 set_tcb_priv_data(tcp, ioc, free);
423 entering_ioc = get_tcb_priv_data(tcp);
426 * retrieve_status, __dev_status called only in case of success,
427 * so it looks like there's no need to check open_count,
428 * event_nr, target_count, dev fields for change (they are
429 * printed only in case of absence of errors).
432 (ioc->version[0] != entering_ioc->version[0]) ||
433 (ioc->version[1] != entering_ioc->version[1]) ||
434 (ioc->version[2] != entering_ioc->version[2]) ||
435 (ioc->data_size != entering_ioc->data_size) ||
436 (ioc->data_start != entering_ioc->data_start) ||
437 (ioc->flags != entering_ioc->flags))
441 if (exiting(tcp) && syserror(tcp) && !ioc_changed)
445 * device mapper code uses %d in some places and %u in another, but
446 * fields themselves are declared as __u32.
448 tprintf("%s{version=%u.%u.%u", entering(tcp) ? ", " : " => ",
449 ioc->version[0], ioc->version[1], ioc->version[2]);
451 * if we use a different version of ABI, do not attempt to decode
454 if (ioc->version[0] != DM_VERSION_MAJOR) {
455 tprints(", /* Unsupported device mapper ABI version */ ...");
459 tprintf(", data_size=%u", ioc->data_size);
461 if (dm_ioctl_has_params(code))
462 tprintf(", data_start=%u", ioc->data_start);
464 if (ioc->data_size < offsetof(struct dm_ioctl, data)) {
465 tprints(", /* Incorrect data_size */ ...");
469 dm_decode_device(code, ioc);
470 dm_decode_values(tcp, code, ioc);
471 dm_decode_flags(ioc);
475 case DM_TABLE_STATUS:
476 if (entering(tcp) || syserror(tcp))
478 dm_decode_dm_target_spec(tcp, arg, ioc);
483 dm_decode_dm_target_spec(tcp, arg, ioc);
486 if (entering(tcp) || syserror(tcp))
488 dm_decode_dm_target_deps(tcp, arg, ioc);
490 case DM_LIST_DEVICES:
491 if (entering(tcp) || syserror(tcp))
493 dm_decode_dm_name_list(tcp, arg, ioc);
495 case DM_LIST_VERSIONS:
496 if (entering(tcp) || syserror(tcp))
498 dm_decode_dm_target_versions(tcp, arg, ioc);
502 dm_decode_dm_target_msg(tcp, arg, ioc);
503 else if (!syserror(tcp) && ioc->flags & DM_DATA_OUT_FLAG)
504 dm_decode_string(tcp, arg, ioc);
507 case DM_DEV_SET_GEOMETRY:
510 dm_decode_string(tcp, arg, ioc);
520 dm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
525 case DM_LIST_DEVICES:
535 case DM_TABLE_STATUS:
536 case DM_LIST_VERSIONS:
538 case DM_DEV_SET_GEOMETRY:
539 return dm_known_ioctl(tcp, code, arg);
545 # else /* !(DM_VERSION_MAJOR == 4) */
548 dm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
553 # endif /* DM_VERSION_MAJOR == 4 */
554 #endif /* HAVE_LINUX_DM_IOCTL_H */