plugin_scsi.c (10870B)
1// SPDX-License-Identifier: GPL-2.0 2#include <stdio.h> 3#include <string.h> 4#include <inttypes.h> 5#include "event-parse.h" 6#include "trace-seq.h" 7 8typedef unsigned long sector_t; 9typedef uint64_t u64; 10typedef unsigned int u32; 11 12/* 13 * SCSI opcodes 14 */ 15#define TEST_UNIT_READY 0x00 16#define REZERO_UNIT 0x01 17#define REQUEST_SENSE 0x03 18#define FORMAT_UNIT 0x04 19#define READ_BLOCK_LIMITS 0x05 20#define REASSIGN_BLOCKS 0x07 21#define INITIALIZE_ELEMENT_STATUS 0x07 22#define READ_6 0x08 23#define WRITE_6 0x0a 24#define SEEK_6 0x0b 25#define READ_REVERSE 0x0f 26#define WRITE_FILEMARKS 0x10 27#define SPACE 0x11 28#define INQUIRY 0x12 29#define RECOVER_BUFFERED_DATA 0x14 30#define MODE_SELECT 0x15 31#define RESERVE 0x16 32#define RELEASE 0x17 33#define COPY 0x18 34#define ERASE 0x19 35#define MODE_SENSE 0x1a 36#define START_STOP 0x1b 37#define RECEIVE_DIAGNOSTIC 0x1c 38#define SEND_DIAGNOSTIC 0x1d 39#define ALLOW_MEDIUM_REMOVAL 0x1e 40 41#define READ_FORMAT_CAPACITIES 0x23 42#define SET_WINDOW 0x24 43#define READ_CAPACITY 0x25 44#define READ_10 0x28 45#define WRITE_10 0x2a 46#define SEEK_10 0x2b 47#define POSITION_TO_ELEMENT 0x2b 48#define WRITE_VERIFY 0x2e 49#define VERIFY 0x2f 50#define SEARCH_HIGH 0x30 51#define SEARCH_EQUAL 0x31 52#define SEARCH_LOW 0x32 53#define SET_LIMITS 0x33 54#define PRE_FETCH 0x34 55#define READ_POSITION 0x34 56#define SYNCHRONIZE_CACHE 0x35 57#define LOCK_UNLOCK_CACHE 0x36 58#define READ_DEFECT_DATA 0x37 59#define MEDIUM_SCAN 0x38 60#define COMPARE 0x39 61#define COPY_VERIFY 0x3a 62#define WRITE_BUFFER 0x3b 63#define READ_BUFFER 0x3c 64#define UPDATE_BLOCK 0x3d 65#define READ_LONG 0x3e 66#define WRITE_LONG 0x3f 67#define CHANGE_DEFINITION 0x40 68#define WRITE_SAME 0x41 69#define UNMAP 0x42 70#define READ_TOC 0x43 71#define READ_HEADER 0x44 72#define GET_EVENT_STATUS_NOTIFICATION 0x4a 73#define LOG_SELECT 0x4c 74#define LOG_SENSE 0x4d 75#define XDWRITEREAD_10 0x53 76#define MODE_SELECT_10 0x55 77#define RESERVE_10 0x56 78#define RELEASE_10 0x57 79#define MODE_SENSE_10 0x5a 80#define PERSISTENT_RESERVE_IN 0x5e 81#define PERSISTENT_RESERVE_OUT 0x5f 82#define VARIABLE_LENGTH_CMD 0x7f 83#define REPORT_LUNS 0xa0 84#define SECURITY_PROTOCOL_IN 0xa2 85#define MAINTENANCE_IN 0xa3 86#define MAINTENANCE_OUT 0xa4 87#define MOVE_MEDIUM 0xa5 88#define EXCHANGE_MEDIUM 0xa6 89#define READ_12 0xa8 90#define SERVICE_ACTION_OUT_12 0xa9 91#define WRITE_12 0xaa 92#define SERVICE_ACTION_IN_12 0xab 93#define WRITE_VERIFY_12 0xae 94#define VERIFY_12 0xaf 95#define SEARCH_HIGH_12 0xb0 96#define SEARCH_EQUAL_12 0xb1 97#define SEARCH_LOW_12 0xb2 98#define SECURITY_PROTOCOL_OUT 0xb5 99#define READ_ELEMENT_STATUS 0xb8 100#define SEND_VOLUME_TAG 0xb6 101#define WRITE_LONG_2 0xea 102#define EXTENDED_COPY 0x83 103#define RECEIVE_COPY_RESULTS 0x84 104#define ACCESS_CONTROL_IN 0x86 105#define ACCESS_CONTROL_OUT 0x87 106#define READ_16 0x88 107#define WRITE_16 0x8a 108#define READ_ATTRIBUTE 0x8c 109#define WRITE_ATTRIBUTE 0x8d 110#define VERIFY_16 0x8f 111#define SYNCHRONIZE_CACHE_16 0x91 112#define WRITE_SAME_16 0x93 113#define SERVICE_ACTION_BIDIRECTIONAL 0x9d 114#define SERVICE_ACTION_IN_16 0x9e 115#define SERVICE_ACTION_OUT_16 0x9f 116/* values for service action in */ 117#define SAI_READ_CAPACITY_16 0x10 118#define SAI_GET_LBA_STATUS 0x12 119/* values for VARIABLE_LENGTH_CMD service action codes 120 * see spc4r17 Section D.3.5, table D.7 and D.8 */ 121#define VLC_SA_RECEIVE_CREDENTIAL 0x1800 122/* values for maintenance in */ 123#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 124#define MI_REPORT_TARGET_PGS 0x0a 125#define MI_REPORT_ALIASES 0x0b 126#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c 127#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d 128#define MI_REPORT_PRIORITY 0x0e 129#define MI_REPORT_TIMESTAMP 0x0f 130#define MI_MANAGEMENT_PROTOCOL_IN 0x10 131/* value for MI_REPORT_TARGET_PGS ext header */ 132#define MI_EXT_HDR_PARAM_FMT 0x20 133/* values for maintenance out */ 134#define MO_SET_IDENTIFYING_INFORMATION 0x06 135#define MO_SET_TARGET_PGS 0x0a 136#define MO_CHANGE_ALIASES 0x0b 137#define MO_SET_PRIORITY 0x0e 138#define MO_SET_TIMESTAMP 0x0f 139#define MO_MANAGEMENT_PROTOCOL_OUT 0x10 140/* values for variable length command */ 141#define XDREAD_32 0x03 142#define XDWRITE_32 0x04 143#define XPWRITE_32 0x06 144#define XDWRITEREAD_32 0x07 145#define READ_32 0x09 146#define VERIFY_32 0x0a 147#define WRITE_32 0x0b 148#define WRITE_SAME_32 0x0d 149 150#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) 151#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) 152 153static const char * 154scsi_trace_misc(struct trace_seq *, unsigned char *, int); 155 156static const char * 157scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) 158{ 159 const char *ret = p->buffer + p->len; 160 sector_t lba = 0, txlen = 0; 161 162 lba |= ((cdb[1] & 0x1F) << 16); 163 lba |= (cdb[2] << 8); 164 lba |= cdb[3]; 165 txlen = cdb[4]; 166 167 trace_seq_printf(p, "lba=%llu txlen=%llu", 168 (unsigned long long)lba, (unsigned long long)txlen); 169 trace_seq_putc(p, 0); 170 return ret; 171} 172 173static const char * 174scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) 175{ 176 const char *ret = p->buffer + p->len; 177 sector_t lba = 0, txlen = 0; 178 179 lba |= (cdb[2] << 24); 180 lba |= (cdb[3] << 16); 181 lba |= (cdb[4] << 8); 182 lba |= cdb[5]; 183 txlen |= (cdb[7] << 8); 184 txlen |= cdb[8]; 185 186 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", 187 (unsigned long long)lba, (unsigned long long)txlen, 188 cdb[1] >> 5); 189 190 if (cdb[0] == WRITE_SAME) 191 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); 192 193 trace_seq_putc(p, 0); 194 return ret; 195} 196 197static const char * 198scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) 199{ 200 const char *ret = p->buffer + p->len; 201 sector_t lba = 0, txlen = 0; 202 203 lba |= (cdb[2] << 24); 204 lba |= (cdb[3] << 16); 205 lba |= (cdb[4] << 8); 206 lba |= cdb[5]; 207 txlen |= (cdb[6] << 24); 208 txlen |= (cdb[7] << 16); 209 txlen |= (cdb[8] << 8); 210 txlen |= cdb[9]; 211 212 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", 213 (unsigned long long)lba, (unsigned long long)txlen, 214 cdb[1] >> 5); 215 trace_seq_putc(p, 0); 216 return ret; 217} 218 219static const char * 220scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) 221{ 222 const char *ret = p->buffer + p->len; 223 sector_t lba = 0, txlen = 0; 224 225 lba |= ((u64)cdb[2] << 56); 226 lba |= ((u64)cdb[3] << 48); 227 lba |= ((u64)cdb[4] << 40); 228 lba |= ((u64)cdb[5] << 32); 229 lba |= (cdb[6] << 24); 230 lba |= (cdb[7] << 16); 231 lba |= (cdb[8] << 8); 232 lba |= cdb[9]; 233 txlen |= (cdb[10] << 24); 234 txlen |= (cdb[11] << 16); 235 txlen |= (cdb[12] << 8); 236 txlen |= cdb[13]; 237 238 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", 239 (unsigned long long)lba, (unsigned long long)txlen, 240 cdb[1] >> 5); 241 242 if (cdb[0] == WRITE_SAME_16) 243 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); 244 245 trace_seq_putc(p, 0); 246 return ret; 247} 248 249static const char * 250scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) 251{ 252 const char *ret = p->buffer + p->len, *cmd; 253 sector_t lba = 0, txlen = 0; 254 u32 ei_lbrt = 0; 255 256 switch (SERVICE_ACTION32(cdb)) { 257 case READ_32: 258 cmd = "READ"; 259 break; 260 case VERIFY_32: 261 cmd = "VERIFY"; 262 break; 263 case WRITE_32: 264 cmd = "WRITE"; 265 break; 266 case WRITE_SAME_32: 267 cmd = "WRITE_SAME"; 268 break; 269 default: 270 trace_seq_printf(p, "UNKNOWN"); 271 goto out; 272 } 273 274 lba |= ((u64)cdb[12] << 56); 275 lba |= ((u64)cdb[13] << 48); 276 lba |= ((u64)cdb[14] << 40); 277 lba |= ((u64)cdb[15] << 32); 278 lba |= (cdb[16] << 24); 279 lba |= (cdb[17] << 16); 280 lba |= (cdb[18] << 8); 281 lba |= cdb[19]; 282 ei_lbrt |= (cdb[20] << 24); 283 ei_lbrt |= (cdb[21] << 16); 284 ei_lbrt |= (cdb[22] << 8); 285 ei_lbrt |= cdb[23]; 286 txlen |= (cdb[28] << 24); 287 txlen |= (cdb[29] << 16); 288 txlen |= (cdb[30] << 8); 289 txlen |= cdb[31]; 290 291 trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", 292 cmd, (unsigned long long)lba, 293 (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); 294 295 if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) 296 trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); 297 298out: 299 trace_seq_putc(p, 0); 300 return ret; 301} 302 303static const char * 304scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) 305{ 306 const char *ret = p->buffer + p->len; 307 unsigned int regions = cdb[7] << 8 | cdb[8]; 308 309 trace_seq_printf(p, "regions=%u", (regions - 8) / 16); 310 trace_seq_putc(p, 0); 311 return ret; 312} 313 314static const char * 315scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) 316{ 317 const char *ret = p->buffer + p->len, *cmd; 318 sector_t lba = 0; 319 u32 alloc_len = 0; 320 321 switch (SERVICE_ACTION16(cdb)) { 322 case SAI_READ_CAPACITY_16: 323 cmd = "READ_CAPACITY_16"; 324 break; 325 case SAI_GET_LBA_STATUS: 326 cmd = "GET_LBA_STATUS"; 327 break; 328 default: 329 trace_seq_printf(p, "UNKNOWN"); 330 goto out; 331 } 332 333 lba |= ((u64)cdb[2] << 56); 334 lba |= ((u64)cdb[3] << 48); 335 lba |= ((u64)cdb[4] << 40); 336 lba |= ((u64)cdb[5] << 32); 337 lba |= (cdb[6] << 24); 338 lba |= (cdb[7] << 16); 339 lba |= (cdb[8] << 8); 340 lba |= cdb[9]; 341 alloc_len |= (cdb[10] << 24); 342 alloc_len |= (cdb[11] << 16); 343 alloc_len |= (cdb[12] << 8); 344 alloc_len |= cdb[13]; 345 346 trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, 347 (unsigned long long)lba, alloc_len); 348 349out: 350 trace_seq_putc(p, 0); 351 return ret; 352} 353 354static const char * 355scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) 356{ 357 switch (SERVICE_ACTION32(cdb)) { 358 case READ_32: 359 case VERIFY_32: 360 case WRITE_32: 361 case WRITE_SAME_32: 362 return scsi_trace_rw32(p, cdb, len); 363 default: 364 return scsi_trace_misc(p, cdb, len); 365 } 366} 367 368static const char * 369scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len) 370{ 371 const char *ret = p->buffer + p->len; 372 373 trace_seq_printf(p, "-"); 374 trace_seq_putc(p, 0); 375 return ret; 376} 377 378const char * 379scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) 380{ 381 switch (cdb[0]) { 382 case READ_6: 383 case WRITE_6: 384 return scsi_trace_rw6(p, cdb, len); 385 case READ_10: 386 case VERIFY: 387 case WRITE_10: 388 case WRITE_SAME: 389 return scsi_trace_rw10(p, cdb, len); 390 case READ_12: 391 case VERIFY_12: 392 case WRITE_12: 393 return scsi_trace_rw12(p, cdb, len); 394 case READ_16: 395 case VERIFY_16: 396 case WRITE_16: 397 case WRITE_SAME_16: 398 return scsi_trace_rw16(p, cdb, len); 399 case UNMAP: 400 return scsi_trace_unmap(p, cdb, len); 401 case SERVICE_ACTION_IN_16: 402 return scsi_trace_service_action_in(p, cdb, len); 403 case VARIABLE_LENGTH_CMD: 404 return scsi_trace_varlen(p, cdb, len); 405 default: 406 return scsi_trace_misc(p, cdb, len); 407 } 408} 409 410unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, 411 unsigned long long *args) 412{ 413 scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]); 414 return 0; 415} 416 417int TEP_PLUGIN_LOADER(struct tep_handle *tep) 418{ 419 tep_register_print_function(tep, 420 process_scsi_trace_parse_cdb, 421 TEP_FUNC_ARG_STRING, 422 "scsi_trace_parse_cdb", 423 TEP_FUNC_ARG_PTR, 424 TEP_FUNC_ARG_PTR, 425 TEP_FUNC_ARG_INT, 426 TEP_FUNC_ARG_VOID); 427 return 0; 428} 429 430void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 431{ 432 tep_unregister_print_function(tep, process_scsi_trace_parse_cdb, 433 "scsi_trace_parse_cdb"); 434}