diff --git a/doc/scst_user_spec.txt b/doc/scst_user_spec.txt index 54c80965f..e85846474 100644 --- a/doc/scst_user_spec.txt +++ b/doc/scst_user_spec.txt @@ -785,6 +785,7 @@ struct scst_user_scsi_cmd_reply_parse { uint8_t queue_type; uint8_t data_direction; + uint8_t write_medium; int32_t data_len; int32_t bufflen; }, @@ -795,6 +796,9 @@ where: - data_direction - command's data flow direction, one of SCST_DATA_* constants + - write_medium - true, if command writes data to medium, so should be + forbidden for read-only devices, false otherwise + - data_len - command's data length - bufflen - command's buffer length diff --git a/scst/include/scst.h b/scst/include/scst.h index 1709c5f15..f6af5fe7c 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -477,12 +477,17 @@ typedef enum dma_data_direction scst_data_direction; enum scst_cdb_flags { /* SCST_TRANSFER_LEN_TYPE_FIXED must be equiv 1 (FIXED_BIT in cdb) */ - SCST_TRANSFER_LEN_TYPE_FIXED = 0x01, - SCST_SMALL_TIMEOUT = 0x02, - SCST_LONG_TIMEOUT = 0x04, - SCST_UNKNOWN_LENGTH = 0x08, - SCST_INFO_INVALID = 0x10, - SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x20, + SCST_TRANSFER_LEN_TYPE_FIXED = 0x001, + SCST_SMALL_TIMEOUT = 0x002, + SCST_LONG_TIMEOUT = 0x004, + SCST_UNKNOWN_LENGTH = 0x008, + SCST_INFO_NOT_FOUND = 0x010, /* must be single bit */ + SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x020, + SCST_IMPLICIT_HQ = 0x040, + SCST_SKIP_UA = 0x080, + SCST_WRITE_MEDIUM = 0x100, + SCST_LOCAL_CMD = 0x200, + SCST_LOCAL_EXEC_NEEDED = 0x400, }; /* @@ -1605,6 +1610,13 @@ struct scst_tgt_dev { /* internal tmp list entry */ struct list_head extra_tgt_dev_list_entry; + + /* + * Stored Unit Attention sense and its length for possible + * subsequent RQUEST SENSE. Both protected by tgt_dev_lock. + */ + unsigned short tgt_dev_valid_sense_len; + uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE]; }; /* @@ -2051,14 +2063,9 @@ enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir); * Returns 1, if cmd's CDB is locally handled by SCST and 0 otherwise. * Dev handlers parse() and dev_done() not called for such commands. */ -static inline int scst_is_cmd_local(struct scst_cmd *cmd) +static inline bool scst_is_cmd_local(struct scst_cmd *cmd) { - int res = 0; - switch (cmd->cdb[0]) { - case REPORT_LUNS: - res = 1; - } - return res; + return (cmd->op_flags & SCST_LOCAL_CMD) != 0; } /* diff --git a/scst/include/scst_const.h b/scst/include/scst_const.h index 376e239a5..bb7af8eea 100644 --- a/scst/include/scst_const.h +++ b/scst/include/scst_const.h @@ -295,7 +295,7 @@ static inline int scst_is_ua_sense(const uint8_t *sense) *************************************************************/ #define SCST_SENSE_ASC_UA_RESET 0x29 #define READ_CAP_LEN 8 -#define READ_CAP16_LEN 12 +#define READ_CAP16_LEN 32 #define BYTCHK 0x02 #define POSITION_LEN_SHORT 20 #define POSITION_LEN_LONG 32 diff --git a/scst/include/scst_user.h b/scst/include/scst_user.h index cc2d7715b..dc2e5cd6d 100644 --- a/scst/include/scst_user.h +++ b/scst/include/scst_user.h @@ -206,6 +206,7 @@ struct scst_user_get_cmd { struct scst_user_scsi_cmd_reply_parse { uint8_t queue_type; uint8_t data_direction; + uint8_t write_medium; int32_t data_len; int32_t bufflen; }; diff --git a/scst/src/dev_handlers/scst_cdrom.c b/scst/src/dev_handlers/scst_cdrom.c index 8437b0975..a73deaff3 100644 --- a/scst/src/dev_handlers/scst_cdrom.c +++ b/scst/src/dev_handlers/scst_cdrom.c @@ -75,7 +75,7 @@ static int cdrom_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_changer.c b/scst/src/dev_handlers/scst_changer.c index bfbd338f6..5c5fdf82c 100644 --- a/scst/src/dev_handlers/scst_changer.c +++ b/scst/src/dev_handlers/scst_changer.c @@ -65,7 +65,7 @@ static int changer_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index 53dbe1738..cba330a15 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -151,7 +151,7 @@ static int disk_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_modisk.c b/scst/src/dev_handlers/scst_modisk.c index fc36709f0..99f5eb360 100644 --- a/scst/src/dev_handlers/scst_modisk.c +++ b/scst/src/dev_handlers/scst_modisk.c @@ -151,7 +151,7 @@ static int modisk_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_processor.c b/scst/src/dev_handlers/scst_processor.c index 3e5e27a12..2caf640a4 100644 --- a/scst/src/dev_handlers/scst_processor.c +++ b/scst/src/dev_handlers/scst_processor.c @@ -65,7 +65,7 @@ static int processor_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_raid.c b/scst/src/dev_handlers/scst_raid.c index 39031356a..37e481c38 100644 --- a/scst/src/dev_handlers/scst_raid.c +++ b/scst/src/dev_handlers/scst_raid.c @@ -65,7 +65,7 @@ static int raid_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 355cc36cf..e2a320ef8 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -154,7 +154,7 @@ static int tape_attach(struct scst_device *dev) TRACE_ENTRY(); if (dev->scsi_dev == NULL || - dev->scsi_dev->type != dev->handler->type) { + dev->scsi_dev->type != dev->type) { PRINT_ERROR("%s", "SCSI device not define or illegal type"); res = -ENODEV; goto out; diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 8d18f9264..52a4510ba 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -760,14 +760,14 @@ static int dev_user_parse(struct scst_cmd *cmd) case SCST_USER_PARSE_STANDARD: TRACE_DBG("PARSE STANDARD: ucmd %p", ucmd); rc = dev->generic_parse(cmd, dev_user_get_block); - if ((rc != 0) || (cmd->op_flags & SCST_INFO_INVALID)) + if ((rc != 0) || (cmd->op_flags & SCST_INFO_NOT_FOUND)) goto out_invalid; break; case SCST_USER_PARSE_EXCEPTION: TRACE_DBG("PARSE EXCEPTION: ucmd %p", ucmd); rc = dev->generic_parse(cmd, dev_user_get_block); - if ((rc == 0) && (!(cmd->op_flags & SCST_INFO_INVALID))) + if ((rc == 0) && (!(cmd->op_flags & SCST_INFO_NOT_FOUND))) break; else if (rc == SCST_CMD_STATE_NEED_THREAD_CTX) { TRACE_MEM("Restarting PARSE to thread context " @@ -828,8 +828,7 @@ out: return res; out_invalid: - PRINT_ERROR("PARSE failed (ucmd %p, rc %d, invalid %d)", ucmd, rc, - cmd->op_flags & SCST_INFO_INVALID); + PRINT_ERROR("PARSE failed (ucmd %p, rc %d)", ucmd, rc); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode)); out_error: @@ -1249,6 +1248,8 @@ static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd, cmd->data_direction = preply->data_direction; cmd->bufflen = preply->bufflen; cmd->data_len = preply->data_len; + if (preply->write_medium) + cmd->op_flags |= SCST_WRITE_MEDIUM; out_process: scst_process_active_cmd(cmd, false); diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 22e07ef0e..654372dfa 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -507,7 +507,7 @@ static int vdisk_attach(struct scst_device *dev) goto out; } - vd = (dev->handler->type == TYPE_DISK) ? + vd = (dev->type == TYPE_DISK) ? &vdisk_dev_list : &vcdrom_dev_list; @@ -530,7 +530,7 @@ static int vdisk_attach(struct scst_device *dev) virt_dev->dev = dev; - if (dev->handler->type == TYPE_ROM) + if (dev->type == TYPE_ROM) virt_dev->rd_only_flag = 1; if (!virt_dev->cdrom_empty) { @@ -547,7 +547,7 @@ static int vdisk_attach(struct scst_device *dev) } else virt_dev->file_size = 0; - if (dev->handler->type == TYPE_DISK) { + if (dev->type == TYPE_DISK) { virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift; } else { @@ -561,7 +561,7 @@ static int vdisk_attach(struct scst_device *dev) PRINT_INFO("Attached SCSI target virtual %s %s " "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld," " cyln=%lld%s)", - (dev->handler->type == TYPE_DISK) ? "disk" : "cdrom", + (dev->type == TYPE_DISK) ? "disk" : "cdrom", virt_dev->name, virt_dev->file_name, virt_dev->file_size >> 20, virt_dev->block_size, (long long unsigned int)virt_dev->nblocks, @@ -1209,7 +1209,7 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd) goto out_put; } - buf[0] = cmd->dev->handler->type; /* type dev */ + buf[0] = cmd->dev->type; /* type dev */ if ((buf[0] == TYPE_ROM) || virt_dev->removable) buf[1] = 0x80; /* removable */ /* Vital Product */ @@ -1548,7 +1548,7 @@ static void vdisk_exec_mode_sense(struct scst_cmd *cmd) blocksize = virt_dev->block_size; nblocks = virt_dev->nblocks; - type = cmd->dev->handler->type; /* type dev */ + type = cmd->dev->type; /* type dev */ dbd = cmd->cdb[1] & DBD; pcontrol = (cmd->cdb[2] & 0xc0) >> 6; pcode = cmd->cdb[2] & 0x3f; @@ -1904,6 +1904,7 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd) nblocks = virt_dev->nblocks - 1; memset(buffer, 0, sizeof(buffer)); + buffer[0] = nblocks >> 56; buffer[1] = (nblocks >> 48) & 0xFF; buffer[2] = (nblocks >> 40) & 0xFF; @@ -1918,6 +1919,25 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd) buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF; buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF; + switch (blocksize) { + case 512: + buffer[13] = 3; + break; + case 1024: + buffer[13] = 2; + break; + case 2048: + buffer[13] = 1; + break; + default: + PRINT_ERROR("%s: Unexpected block size %d", + cmd->op_name, blocksize); + /* go through */ + case 4096: + buffer[13] = 0; + break; + } + length = scst_get_buf_first(cmd, &address); if (unlikely(length <= 0)) { if (length < 0) { @@ -1953,7 +1973,7 @@ static void vdisk_exec_read_toc(struct scst_cmd *cmd) TRACE_ENTRY(); - if (cmd->dev->handler->type != TYPE_ROM) { + if (cmd->dev->type != TYPE_ROM) { PRINT_ERROR("%s", "READ TOC for non-CDROM device"); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode)); @@ -2040,7 +2060,7 @@ static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd) TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]); - if (cmd->dev->handler->type == TYPE_ROM) { + if (cmd->dev->type == TYPE_ROM) { spin_lock(&virt_dev->flags_lock); virt_dev->prevent_allow_medium_removal = cmd->cdb[4] & 0x01 ? 1 : 0; diff --git a/scst/src/scst_cdbprobe.h b/scst/src/scst_cdbprobe.h index dc9ca6006..23f3e0d30 100644 --- a/scst/src/scst_cdbprobe.h +++ b/scst/src/scst_cdbprobe.h @@ -31,6 +31,7 @@ static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off); /* for special commands */ static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off); static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off); +static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off); static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off); static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off); static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off); @@ -80,7 +81,7 @@ struct scst_sdbops { uint8_t direction; /* init --> target: SCST_DATA_WRITE * target --> init: SCST_DATA_READ */ - uint8_t flags; /* opcode -- various flags */ + uint16_t flags; /* opcode -- various flags */ uint8_t off; /* length offset in cdb */ int (*get_trans_len)(struct scst_cmd *cmd, uint8_t off) __attribute__ ((aligned)); @@ -111,7 +112,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = { /* 6-bytes length CDB */ {0x00, "MMMMMMMMMMMMMMMM", "TEST UNIT READY", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, + /* let's be HQ to don't look dead under high load */ + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ, 0, get_trans_len_none}, {0x01, " M ", "REWIND", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x01, "O V OO OO ", "REZERO UNIT", @@ -119,12 +121,13 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x02, "VVVVVV V ", "REQUEST BLOCK ADDR", SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, {0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE", - SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1}, + SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_EXEC_NEEDED, + 4, get_trans_len_1}, {0x04, "M O O ", "FORMAT UNIT", - SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH, + SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x04, " O ", "FORMAT", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x05, "VMVVVV V ", "READ BLOCK LIMITS", SCST_DATA_READ, SCST_SMALL_TIMEOUT, 0, get_trans_len_block_limit}, {0x06, "VVVVVV V ", "", @@ -132,7 +135,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x07, " O ", "INITIALIZE ELEMENT STATUS", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x07, "OVV O OV ", "REASSIGN BLOCKS", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x08, "O ", "READ(6)", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256}, {0x08, " MV OO OV ", "READ(6)", @@ -144,9 +147,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x09, "VVVVVV V ", "", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x0A, "O ", "WRITE(6)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 4, get_trans_len_1_256}, {0x0A, " M O OV ", "WRITE(6)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 2, get_trans_len_3}, {0x0A, " M ", "PRINT", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x0A, " M ", "SEND MESSAGE(6)", @@ -162,19 +167,21 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x0C, "VVVVVV V ", "SEEK BLOCK", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x0D, "VVVVVV V ", "PARTITION", - SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM, + 0, get_trans_len_none}, {0x0E, "VVVVVV V ", "", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x0F, "VOVVVV V ", "READ REVERSE", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3}, {0x10, "VM V V ", "WRITE FILEMARKS", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x10, " O O ", "SYNCHRONIZE BUFFER", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x11, "VMVVVV ", "SPACE", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x12, "MMMMMMMMMMMMMMMM", "INQUIRY", - SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1}, + SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA, + 4, get_trans_len_1}, {0x13, "VOVVVV ", "VERIFY(6)", SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED, @@ -182,15 +189,18 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x14, "VOOVVV ", "RECOVER BUFFERED DATA", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3}, {0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)", - SCST_DATA_WRITE, FLAG_NONE, 4, get_trans_len_1}, + SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 4, get_trans_len_1}, {0x16, "MMMMMMMMMMMMMMMM", "RESERVE", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + 0, get_trans_len_none}, {0x17, "MMMMMMMMMMMMMMMM", "RELEASE", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + 0, get_trans_len_none}, {0x18, "OOOOOOOO ", "COPY", SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3}, {0x19, "VMVVVV ", "ERASE", - SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM, + 0, get_trans_len_none}, {0x1A, "OMOOOOOOOOOOOOOO", "MODE SENSE(6)", SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1}, {0x1B, " O ", "SCAN", @@ -222,7 +232,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x24, "V VVM ", "SET WINDOW", SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3}, {0x25, "M MM M ", "READ CAPACITY", - SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_read_capacity}, + SCST_DATA_READ, SCST_IMPLICIT_HQ, 0, get_trans_len_read_capacity}, {0x25, " O ", "GET WINDOW", SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_3}, {0x26, "V VV ", "", @@ -236,7 +246,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x29, "V VV O ", "READ GENERATION", SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1}, {0x2A, "O MO M ", "WRITE(10)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 7, get_trans_len_2}, {0x2A, " O ", "SEND MESSAGE(10)", SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2}, {0x2A, " O ", "SEND(10)", @@ -248,11 +259,13 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x2B, "O OO O ", "SEEK(10)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x2C, "V O O ", "ERASE(10)", - SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM, + 0, get_trans_len_none}, {0x2D, "V O O ", "READ UPDATED BLOCK", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 0, get_trans_len_single}, {0x2E, "O OO O ", "WRITE AND VERIFY(10)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 7, get_trans_len_2}, {0x2F, "O OO O ", "VERIFY(10)", SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED, @@ -287,11 +300,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x3E, "O OO O ", "READ LONG", SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, {0x3F, "O O O ", "WRITE LONG", - SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2}, + SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 7, get_trans_len_2}, {0x40, "OOOOOOOOOO ", "CHANGE DEFINITION", SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 8, get_trans_len_1}, {0x41, "O O ", "WRITE SAME", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, 0, get_trans_len_single}, {0x42, " O ", "READ SUB-CHANNEL", SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, @@ -324,11 +337,11 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x4F, " ", "", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x50, " ", "XDWRITE", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x51, " O ", "READ DISC INFORMATION", SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, {0x51, " ", "XPWRITE", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x52, " O ", "READ TRACK INFORMATION", SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, {0x53, " O ", "RESERVE TRACK", @@ -336,13 +349,15 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x54, " O ", "SEND OPC INFORMATION", SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2}, {0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)", - SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2}, + SCST_DATA_WRITE, SCST_LOCAL_EXEC_NEEDED, 7, get_trans_len_2}, {0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + 0, get_trans_len_none}, {0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)", - SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_EXEC_NEEDED, + 0, get_trans_len_none}, {0x58, " O ", "REPAIR TRACK", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x59, " ", "", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x5A, "OOOOOOOOOOOOOOOO", "MODE SENSE(10)", @@ -353,22 +368,22 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2}, {0x5D, " O ", "SEND CUE SHEET", SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3}, - {0x5E, "OOOOO OOOO ", "PERSISTENT_RESERV_IN", + {0x5E, "OOOOO OOOO ", "PERSISTENT RESERV IN", SCST_DATA_READ, FLAG_NONE, 5, get_trans_len_4}, - {0x5F, "OOOOO OOOO ", "PERSISTENT_RESERV_OUT", + {0x5F, "OOOOO OOOO ", "PERSISTENT RESERV OUT", SCST_DATA_WRITE, FLAG_NONE, 5, get_trans_len_4}, /* 16-bytes length CDB */ {0x80, "O OO O ", "XDWRITE EXTENDED", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x80, " M ", "WRITE FILEMARKS", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0x81, "O OO O ", "REBUILD", - SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4}, {0x82, "O OO O ", "REGENERATE", - SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4}, {0x83, "OOOOOOOOOOOOOOOO", "EXTENDED COPY", - SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4}, {0x84, "OOOOOOOOOOOOOOOO", "RECEIVE COPY RESULT", SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4}, {0x86, "OOOOOOOOOO ", "ACCESS CONTROL IN", @@ -378,13 +393,15 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x88, "M MMMM ", "READ(16)", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4}, {0x8A, "O OO O ", "WRITE(16)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 10, get_trans_len_4}, {0x8C, "OOOOOOOOOO ", "READ ATTRIBUTE", SCST_DATA_READ, FLAG_NONE, 10, get_trans_len_4}, {0x8D, "OOOOOOOOOO ", "WRITE ATTRIBUTE", - SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4}, {0x8E, "O OO O ", "WRITE AND VERIFY(16)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 10, get_trans_len_4}, {0x8F, "O OO O ", "VERIFY(16)", SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED, @@ -400,15 +417,19 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0x92, " O ", "LOCATE(16)", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0x93, "O O ", "WRITE SAME(16)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 10, get_trans_len_4}, {0x93, " M ", "ERASE(16)", - SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM, + 0, get_trans_len_none}, {0x9E, "O ", "SERVICE ACTION IN", - SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, + SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_serv_act_in}, /* 12-bytes length CDB */ - {0xA0, "VVVVVVVVVV M ", "REPORT LUN", - SCST_DATA_READ, SCST_SMALL_TIMEOUT, 6, get_trans_len_4}, + {0xA0, "VVVVVVVVVV M ", "REPORT LUNS", + SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA| + SCST_LOCAL_CMD|SCST_LOCAL_EXEC_NEEDED, + 6, get_trans_len_4}, {0xA1, " O ", "BLANK", SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none}, {0xA2, " ", "", @@ -438,19 +459,21 @@ static const struct scst_sdbops scst_scsi_op_table[] = { {0xA9, " O ", "PLAY TRACK RELATIVE(12)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0xAA, "O OO O ", "WRITE(12)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_4}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 6, get_trans_len_4}, {0xAA, " O ", "SEND MESSAGE(12)", SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4}, {0xAB, " ", "", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0xAC, " O ", "ERASE(12)", - SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, + SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none}, {0xAC, " M ", "GET PERFORMANCE", SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none}, {0xAD, " O ", "READ DVD STRUCTURE", SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2}, {0xAE, "O OO O ", "WRITE AND VERIFY(12)", - SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_4}, + SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, + 6, get_trans_len_4}, {0xAF, "O OO O ", "VERIFY(12)", SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED, @@ -505,14 +528,6 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none} }; -/* Notes: - Unknown op's: - #define SCSIOP_XDWRITE_EXTENDED 0x80 - #define SCSIOP_REBUILD 0x81 - #define SCSIOP_EA 0xea - #define WRITE_LONG_2 0xea -*/ - #define SCST_CDB_TBL_SIZE \ ((int)(sizeof(scst_scsi_op_table)/sizeof(struct scst_sdbops))) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index b212a5e7c..bcc78cd7c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -2487,6 +2487,23 @@ static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off) return 0; } +static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off) +{ + int res = 0; + + TRACE_ENTRY(); + + if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) { + cmd->op_name = "READ CAPACITY(16)"; + cmd->bufflen = READ_CAP16_LEN; + cmd->op_flags |= SCST_IMPLICIT_HQ; + } else + cmd->op_flags |= SCST_UNKNOWN_LENGTH; + + TRACE_EXIT_RES(res); + return res; +} + static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off) { cmd->bufflen = 1; @@ -2600,7 +2617,7 @@ static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off) int scst_get_cdb_info(struct scst_cmd *cmd) { - int dev_type = cmd->dev->handler->type; + int dev_type = cmd->dev->type; int i, res = 0; uint8_t op; const struct scst_sdbops *ptr = NULL; @@ -2638,12 +2655,12 @@ int scst_get_cdb_info(struct scst_cmd *cmd) i++; } - if (ptr == NULL) { + if (unlikely(ptr == NULL)) { /* opcode not found or now not used !!! */ TRACE(TRACE_SCSI, "Unknown opcode 0x%x for type %d", op, dev_type); res = -1; - cmd->op_flags = SCST_INFO_INVALID; + cmd->op_flags = SCST_INFO_NOT_FOUND; goto out; } @@ -2654,7 +2671,7 @@ int scst_get_cdb_info(struct scst_cmd *cmd) res = (*ptr->get_trans_len)(cmd, ptr->off); out: - TRACE_EXIT(); + TRACE_EXIT_RES(res); return res; } EXPORT_SYMBOL(scst_get_cdb_info); @@ -2811,12 +2828,6 @@ int scst_sbc_generic_parse(struct scst_cmd *cmd, cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen); switch (cmd->cdb[0]) { - case SERVICE_ACTION_IN: - if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) { - cmd->bufflen = READ_CAP16_LEN; - cmd->data_direction = SCST_DATA_READ; - } - break; case VERIFY_6: case VERIFY: case VERIFY_12: diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index f87e12486..224e20edf 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -413,23 +413,14 @@ void scst_process_reset(struct scst_device *dev, struct scst_session *originator, struct scst_cmd *exclude_cmd, struct scst_mgmt_cmd *mcmd, bool setUA); -static inline int scst_is_ua_command(struct scst_cmd *cmd) +static inline bool scst_is_ua_command(struct scst_cmd *cmd) { - return (cmd->cdb[0] != INQUIRY) && - (cmd->cdb[0] != REQUEST_SENSE) && - (cmd->cdb[0] != REPORT_LUNS); + return (cmd->op_flags & SCST_SKIP_UA) == 0; } -static inline int scst_is_implicit_hq(struct scst_cmd *cmd) +static inline bool scst_is_implicit_hq(struct scst_cmd *cmd) { - return (cmd->cdb[0] == INQUIRY) || - (cmd->cdb[0] == REPORT_LUNS) || - ((cmd->dev->type == TYPE_DISK) && - ((cmd->cdb[0] == READ_CAPACITY) || - ((cmd->cdb[0] == SERVICE_ACTION_IN) && - ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16)))) || - /* Let's don't look dead under high load */ - (cmd->cdb[0] == TEST_UNIT_READY); + return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0; } /* diff --git a/scst/src/scst_proc.c b/scst/src/scst_proc.c index 5c3dce36e..9b1db4cd2 100644 --- a/scst/src/scst_proc.c +++ b/scst/src/scst_proc.c @@ -1460,7 +1460,7 @@ static int scst_proc_assign_handler(char *buf) if (dev->scsi_dev->type != handler->type) { PRINT_ERROR("Type %d of device %s differs from type " - "%d of dev handler %s", dev->handler->type, + "%d of dev handler %s", dev->type, dev->handler->name, handler->type, handler->name); res = -EINVAL; goto out; diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 6bd888c58..e65c9cd71 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -1440,7 +1440,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd) if (unlikely(buffer_size == 0)) goto out_compl; else if (unlikely(buffer_size < 0)) - goto out_err; + goto out_hw_err; if (buffer_size < 16) goto out_put_err; @@ -1491,7 +1491,7 @@ inc_dev_cnt: if (unlikely(buffer_size == 0)) goto out_compl; else if (unlikely(buffer_size < 0)) - goto out_err; + goto out_hw_err; dev_cnt *= 8; buffer[0] = (dev_cnt >> 24) & 0xff; @@ -1557,10 +1557,108 @@ out_err: out_put_hw_err: scst_put_buf(cmd, buffer); + +out_hw_err: scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); goto out_compl; } +static int scst_request_sense_local(struct scst_cmd *cmd) +{ + int res = SCST_EXEC_COMPLETED, rc; + struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; + uint8_t *buffer; + int buffer_size = 0; + + TRACE_ENTRY(); + + rc = scst_check_local_events(cmd); + if (unlikely(rc != 0)) + goto out_done; + + cmd->status = 0; + cmd->msg_status = 0; + cmd->host_status = DID_OK; + cmd->driver_status = 0; + + spin_lock_bh(&tgt_dev->tgt_dev_lock); + + if (tgt_dev->tgt_dev_valid_sense_len == 0) + goto out_not_completed; + + TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name); + + buffer_size = scst_get_buf_first(cmd, &buffer); + if (unlikely(buffer_size == 0)) + goto out_compl; + else if (unlikely(buffer_size < 0)) + goto out_hw_err; + + memset(buffer, 0, buffer_size); + + if (((tgt_dev->tgt_dev_sense[0] == 0x70) || + (tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) { + PRINT_WARNING("%s: Fixed format of the saved sense, but " + "descriptor format requested. Convertion will " + "truncated data", cmd->op_name); + PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense, + tgt_dev->tgt_dev_valid_sense_len); + + buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size); + scst_set_sense(buffer, buffer_size, true, + tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12], + tgt_dev->tgt_dev_sense[13]); + } else if (((tgt_dev->tgt_dev_sense[0] == 0x72) || + (tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) { + PRINT_WARNING("%s: Descriptor format of the " + "saved sense, but fixed format requested. Convertion " + "will truncated data", cmd->op_name); + PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense, + tgt_dev->tgt_dev_valid_sense_len); + + buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size); + scst_set_sense(buffer, buffer_size, false, + tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2], + tgt_dev->tgt_dev_sense[3]); + } else { + if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len) + buffer_size = tgt_dev->tgt_dev_valid_sense_len; + else { + PRINT_WARNING("%s: Being returned sense truncated to " + "size %d (needed %d)", cmd->op_name, + buffer_size, tgt_dev->tgt_dev_valid_sense_len); + } + memcpy(buffer, tgt_dev->tgt_dev_sense, buffer_size); + } + + scst_put_buf(cmd, buffer); + +out_compl: + tgt_dev->tgt_dev_valid_sense_len = 0; + scst_set_resp_data_len(cmd, buffer_size); + + spin_unlock_bh(&tgt_dev->tgt_dev_lock); + + cmd->completed = 1; + +out_done: + /* Report the result */ + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); + +out: + TRACE_EXIT_RES(res); + return res; + +out_hw_err: + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + goto out_compl; + +out_not_completed: + spin_unlock_bh(&tgt_dev->tgt_dev_lock); + res = SCST_EXEC_NOT_COMPLETED; + goto out; +} + static int scst_pre_select(struct scst_cmd *cmd) { int res = SCST_EXEC_NOT_COMPLETED; @@ -2044,16 +2142,8 @@ static int scst_do_local_exec(struct scst_cmd *cmd) TRACE_ENTRY(); /* Check READ_ONLY device status */ - if (((tgt_dev->acg_dev->rd_only_flag) || cmd->dev->swp) && - (cmd->cdb[0] == WRITE_6 || /* ToDo: full list of the modify cmds */ - cmd->cdb[0] == WRITE_10 || - cmd->cdb[0] == WRITE_12 || - cmd->cdb[0] == WRITE_16 || - cmd->cdb[0] == WRITE_VERIFY || - cmd->cdb[0] == WRITE_VERIFY_12 || - cmd->cdb[0] == WRITE_VERIFY_16 || - (cmd->dev->handler->type == TYPE_TAPE && - (cmd->cdb[0] == ERASE || cmd->cdb[0] == WRITE_FILEMARKS)))) { + if ((cmd->op_flags & SCST_WRITE_MEDIUM) && + ((tgt_dev->acg_dev->rd_only_flag) || cmd->dev->swp)) { PRINT_WARNING("Attempt of write access to read-only device: " "initiator %s, LUN %lld, op %x", cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]); @@ -2067,6 +2157,11 @@ static int scst_do_local_exec(struct scst_cmd *cmd) * scst_is_cmd_local() in scst.h, if necessary */ + if (!(cmd->op_flags & SCST_LOCAL_EXEC_NEEDED)) { + res = SCST_EXEC_NOT_COMPLETED; + goto out; + } + switch (cmd->cdb[0]) { case MODE_SELECT: case MODE_SELECT_10: @@ -2084,6 +2179,9 @@ static int scst_do_local_exec(struct scst_cmd *cmd) case REPORT_LUNS: res = scst_report_luns_local(cmd); break; + case REQUEST_SENSE: + res = scst_request_sense_local(cmd); + break; default: res = SCST_EXEC_NOT_COMPLETED; break; @@ -2453,7 +2551,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd) goto out; if (likely(scsi_status_is_good(cmd->status))) { - unsigned char type = cmd->dev->handler->type; + unsigned char type = cmd->dev->type; if (unlikely((cmd->cdb[0] == MODE_SENSE || cmd->cdb[0] == MODE_SENSE_10)) && cmd->tgt_dev->acg_dev->rd_only_flag && @@ -2824,6 +2922,28 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd) if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) scst_xmit_process_aborted_cmd(cmd); + else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) && + SCST_SENSE_VALID(cmd->sense) && + !test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags)) { + struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; + + TRACE_DBG("Storing sense (cmd %p)", cmd); + + spin_lock_bh(&tgt_dev->tgt_dev_lock); + + if (cmd->sense_bufflen <= sizeof(tgt_dev->tgt_dev_sense)) + tgt_dev->tgt_dev_valid_sense_len = cmd->sense_bufflen; + else { + tgt_dev->tgt_dev_valid_sense_len = sizeof(tgt_dev->tgt_dev_sense); + PRINT_ERROR("Stored sense truncated to size %d " + "(needed %d)", tgt_dev->tgt_dev_valid_sense_len, + cmd->sense_bufflen); + } + memcpy(tgt_dev->tgt_dev_sense, cmd->sense, + tgt_dev->tgt_dev_valid_sense_len); + + spin_unlock_bh(&tgt_dev->tgt_dev_lock); + } if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) { TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu)," diff --git a/usr/fileio/common.c b/usr/fileio/common.c index b94da9423..b1f55051d 100644 --- a/usr/fileio/common.c +++ b/usr/fileio/common.c @@ -1469,6 +1469,7 @@ static void exec_read_capacity16(struct vdisk_cmd *vcmd) nblocks = dev->nblocks - 1; memset(buffer, 0, sizeof(buffer)); + buffer[0] = nblocks >> 56; buffer[1] = (nblocks >> 48) & 0xFF; buffer[2] = (nblocks >> 40) & 0xFF; @@ -1483,6 +1484,25 @@ static void exec_read_capacity16(struct vdisk_cmd *vcmd) buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF; buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF; + switch (blocksize) { + case 512: + buffer[13] = 3; + break; + case 1024: + buffer[13] = 2; + break; + case 2048: + buffer[13] = 1; + break; + default: + PRINT_ERROR("READ CAPACITY(16): Unexpected block size %d6", + blocksize); + /* go through */ + case 4096: + buffer[13] = 0; + break; + } + if (length > READ_CAP16_LEN) length = READ_CAP16_LEN; memcpy(address, buffer, length);