qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

scsi: explicitly list guest-recoverable sense codes

It's not really possible to fit all sense codes into errno codes,
especially in such a way that sense codes can be properly categorized as
either guest-recoverable or host-handled. Create a new function that
checks for guest recoverable sense, then scsi_sense_buf_to_errno only
needs to be called for host handled sense codes.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+46 -3
+2 -3
hw/scsi/scsi-disk.c
··· 454 454 * pause the host. 455 455 */ 456 456 assert(r->status && *r->status); 457 - error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); 458 - if (error == ECANCELED || error == EAGAIN || error == ENOTCONN || 459 - error == 0) { 457 + if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { 460 458 /* These errors are handled by guest. */ 461 459 sdc->update_sense(&r->req); 462 460 scsi_req_complete(&r->req, *r->status); 463 461 return true; 464 462 } 463 + error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); 465 464 break; 466 465 case ENOMEDIUM: 467 466 scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
+1
include/scsi/utils.h
··· 106 106 107 107 int scsi_sense_to_errno(int key, int asc, int ascq); 108 108 int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size); 109 + bool scsi_sense_buf_is_guest_recoverable(const uint8_t *sense, size_t sense_size); 109 110 110 111 int scsi_convert_sense(uint8_t *in_buf, int in_len, 111 112 uint8_t *buf, int len, bool fixed);
+43
scsi/utils.c
··· 336 336 } 337 337 } 338 338 339 + static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq) 340 + { 341 + switch (key) { 342 + case NO_SENSE: 343 + case RECOVERED_ERROR: 344 + case UNIT_ATTENTION: 345 + case ABORTED_COMMAND: 346 + return true; 347 + case NOT_READY: 348 + case ILLEGAL_REQUEST: 349 + case DATA_PROTECT: 350 + /* Parse ASCQ */ 351 + break; 352 + default: 353 + return false; 354 + } 355 + 356 + switch ((asc << 8) | ascq) { 357 + case 0x1a00: /* PARAMETER LIST LENGTH ERROR */ 358 + case 0x2000: /* INVALID OPERATION CODE */ 359 + case 0x2400: /* INVALID FIELD IN CDB */ 360 + case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */ 361 + case 0x2600: /* INVALID FIELD IN PARAMETER LIST */ 362 + 363 + case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */ 364 + case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */ 365 + return true; 366 + default: 367 + return false; 368 + } 369 + } 370 + 339 371 int scsi_sense_to_errno(int key, int asc, int ascq) 340 372 { 341 373 switch (key) { ··· 389 421 390 422 sense = scsi_parse_sense_buf(in_buf, in_len); 391 423 return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq); 424 + } 425 + 426 + bool scsi_sense_buf_is_guest_recoverable(const uint8_t *in_buf, size_t in_len) 427 + { 428 + SCSISense sense; 429 + if (in_len < 1) { 430 + return false; 431 + } 432 + 433 + sense = scsi_parse_sense_buf(in_buf, in_len); 434 + return scsi_sense_is_guest_recoverable(sense.key, sense.asc, sense.ascq); 392 435 } 393 436 394 437 const char *scsi_command_name(uint8_t cmd)