Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sg_io_v3.c 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
  3. * Copyright (c) 2007-2018 Dmitry V. Levin <ldv@altlinux.org>
  4. * Copyright (c) 2015 Bart Van Assche <bart.vanassche@sandisk.com>
  5. * All rights reserved.
  6. *
  7. * SPDX-License-Identifier: LGPL-2.1-or-later
  8. */
  9. #include "defs.h"
  10. #ifdef HAVE_SCSI_SG_H
  11. # include DEF_MPERS_TYPE(struct_sg_io_hdr)
  12. # include <scsi/sg.h>
  13. typedef struct sg_io_hdr struct_sg_io_hdr;
  14. #endif /* HAVE_SCSI_SG_H */
  15. #include MPERS_DEFS
  16. #include "xlat/sg_io_info.h"
  17. #ifdef HAVE_SCSI_SG_H
  18. # include "print_fields.h"
  19. # include "xlat/sg_io_dxfer_direction.h"
  20. # include "xlat/sg_io_flags.h"
  21. static void
  22. print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr,
  23. const unsigned int data_size, const unsigned int iovec_count)
  24. {
  25. if (iovec_count) {
  26. tprint_iov_upto(tcp, iovec_count, addr, IOV_DECODE_STR,
  27. data_size);
  28. } else {
  29. printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX);
  30. }
  31. }
  32. # define PRINT_FIELD_SG_IO_BUFFER(prefix_, where_, field_, size_, count_, tcp_) \
  33. do { \
  34. STRACE_PRINTF("%s%s=", (prefix_), #field_); \
  35. print_sg_io_buffer((tcp_), (mpers_ptr_t)((where_).field_), \
  36. (size_), (count_)); \
  37. } while (0)
  38. static int
  39. decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
  40. {
  41. struct_sg_io_hdr sg_io;
  42. static const size_t skip_iid =
  43. offsetof(struct_sg_io_hdr, dxfer_direction);
  44. tprints("{interface_id='S', ");
  45. if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid,
  46. &sg_io.dxfer_direction)) {
  47. tprints("}");
  48. return RVAL_IOCTL_DECODED;
  49. }
  50. PRINT_FIELD_XVAL("", sg_io, dxfer_direction, sg_io_dxfer_direction,
  51. "SG_DXFER_???");
  52. PRINT_FIELD_U(", ", sg_io, cmd_len);
  53. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, cmdp, sg_io.cmd_len, 0, tcp);
  54. PRINT_FIELD_U(", ", sg_io, mx_sb_len);
  55. PRINT_FIELD_U(", ", sg_io, iovec_count);
  56. PRINT_FIELD_U(", ", sg_io, dxfer_len);
  57. PRINT_FIELD_U(", ", sg_io, timeout);
  58. PRINT_FIELD_FLAGS(", ", sg_io, flags, sg_io_flags, "SG_FLAG_???");
  59. if (sg_io.dxfer_direction == SG_DXFER_TO_DEV ||
  60. sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
  61. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, dxferp, sg_io.dxfer_len, sg_io.iovec_count, tcp);
  62. }
  63. struct_sg_io_hdr *entering_sg_io = malloc(sizeof(*entering_sg_io));
  64. if (entering_sg_io) {
  65. memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
  66. entering_sg_io->interface_id = (unsigned char) 'S';
  67. set_tcb_priv_data(tcp, entering_sg_io, free);
  68. }
  69. return 0;
  70. }
  71. static int
  72. decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
  73. {
  74. struct_sg_io_hdr *entering_sg_io = get_tcb_priv_data(tcp);
  75. struct_sg_io_hdr sg_io;
  76. if (umove(tcp, arg, &sg_io) < 0) {
  77. /* print i/o fields fetched on entering syscall */
  78. if (entering_sg_io->dxfer_direction == SG_DXFER_FROM_DEV)
  79. PRINT_FIELD_PTR(", ", *entering_sg_io, dxferp);
  80. PRINT_FIELD_PTR(", ", *entering_sg_io, sbp);
  81. return RVAL_IOCTL_DECODED;
  82. }
  83. if (sg_io.interface_id != entering_sg_io->interface_id) {
  84. PRINT_FIELD_U(" => ", sg_io, interface_id);
  85. return RVAL_IOCTL_DECODED;
  86. }
  87. if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV ||
  88. sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
  89. uint32_t din_len = sg_io.dxfer_len;
  90. const char *prefix = NULL;
  91. if (sg_io.resid > 0 && (unsigned int) sg_io.resid <= din_len)
  92. din_len -= sg_io.resid;
  93. if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV)
  94. prefix = ", ";
  95. else if (din_len)
  96. prefix = " => ";
  97. if (prefix) {
  98. tprints(prefix);
  99. PRINT_FIELD_SG_IO_BUFFER("", sg_io, dxferp, din_len,
  100. sg_io.iovec_count, tcp);
  101. }
  102. }
  103. PRINT_FIELD_X(", ", sg_io, status);
  104. PRINT_FIELD_X(", ", sg_io, masked_status);
  105. PRINT_FIELD_X(", ", sg_io, msg_status);
  106. PRINT_FIELD_U(", ", sg_io, sb_len_wr);
  107. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, sbp, sg_io.sb_len_wr, 0, tcp);
  108. PRINT_FIELD_X(", ", sg_io, host_status);
  109. PRINT_FIELD_X(", ", sg_io, driver_status);
  110. PRINT_FIELD_D(", ", sg_io, resid);
  111. PRINT_FIELD_U(", ", sg_io, duration);
  112. PRINT_FIELD_FLAGS(", ", sg_io, info, sg_io_info, "SG_INFO_???");
  113. return RVAL_IOCTL_DECODED;
  114. }
  115. #else /* !HAVE_SCSI_SG_H */
  116. static int
  117. decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
  118. {
  119. tprints("{interface_id='S', ...}");
  120. return RVAL_IOCTL_DECODED;
  121. }
  122. static int
  123. decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
  124. {
  125. return 0;
  126. }
  127. #endif
  128. MPERS_PRINTER_DECL(int, decode_sg_io_v3,
  129. struct tcb *const tcp, const kernel_ulong_t arg)
  130. {
  131. return entering(tcp) ? decode_request(tcp, arg)
  132. : decode_response(tcp, arg);
  133. }