From 6b29b72695660a2f4a8ac1dc8049a6f0b6b7cad6 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 23 Oct 2012 01:05:31 +0000 Subject: [PATCH] - Fix lost residual for allowed to mismatch data transfer direction commands - Fix sending unneeded Control Mode Page MODE SENSE commands. Some devices may not support this page, so extra calls only fill logs with pointless warnings git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4565 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 3 ++- scst/src/dev_handlers/scst_cdrom.c | 2 +- scst/src/dev_handlers/scst_changer.c | 2 +- scst/src/dev_handlers/scst_disk.c | 2 +- scst/src/dev_handlers/scst_modisk.c | 2 +- scst/src/dev_handlers/scst_processor.c | 2 +- scst/src/dev_handlers/scst_raid.c | 2 +- scst/src/dev_handlers/scst_tape.c | 2 +- scst/src/scst_lib.c | 24 ++++++++++++++++++++---- scst/src/scst_targ.c | 8 ++++---- 10 files changed, 33 insertions(+), 16 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 1cb370e6e..d01a6dec6 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -4221,7 +4221,8 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd, int scst_tape_generic_dev_done(struct scst_cmd *cmd, void (*set_block_size)(struct scst_cmd *cmd, int block_size)); -int scst_obtain_device_parameters(struct scst_device *dev); +int scst_obtain_device_parameters(struct scst_device *dev, + const uint8_t *mode_select_cdb); void scst_reassign_retained_sess_states(struct scst_session *new_sess, struct scst_session *old_sess); diff --git a/scst/src/dev_handlers/scst_cdrom.c b/scst/src/dev_handlers/scst_cdrom.c index 4ba61559e..921ac34e4 100644 --- a/scst/src/dev_handlers/scst_cdrom.c +++ b/scst/src/dev_handlers/scst_cdrom.c @@ -139,7 +139,7 @@ static int cdrom_attach(struct scst_device *dev) } dev->block_size = 1 << dev->block_shift; - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/dev_handlers/scst_changer.c b/scst/src/dev_handlers/scst_changer.c index f02f2bc04..4d44c2742 100644 --- a/scst/src/dev_handlers/scst_changer.c +++ b/scst/src/dev_handlers/scst_changer.c @@ -98,7 +98,7 @@ static int changer_attach(struct scst_device *dev) /* Let's try not to be too smart and continue processing */ } - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index f05cde7ad..1bd18e6d7 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -231,7 +231,7 @@ static int disk_attach(struct scst_device *dev) } dev->block_size = 1 << dev->block_shift; - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/dev_handlers/scst_modisk.c b/scst/src/dev_handlers/scst_modisk.c index 01ef61efe..434696179 100644 --- a/scst/src/dev_handlers/scst_modisk.c +++ b/scst/src/dev_handlers/scst_modisk.c @@ -238,7 +238,7 @@ static int modisk_attach(struct scst_device *dev) } dev->block_size = 1 << dev->block_shift; - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s: %x", dev->virt_name, res); diff --git a/scst/src/dev_handlers/scst_processor.c b/scst/src/dev_handlers/scst_processor.c index 2bf78fdc9..6ccde9e5a 100644 --- a/scst/src/dev_handlers/scst_processor.c +++ b/scst/src/dev_handlers/scst_processor.c @@ -98,7 +98,7 @@ static int processor_attach(struct scst_device *dev) /* Let's try not to be too smart and continue processing */ } - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/dev_handlers/scst_raid.c b/scst/src/dev_handlers/scst_raid.c index d43af231e..3ff78b89c 100644 --- a/scst/src/dev_handlers/scst_raid.c +++ b/scst/src/dev_handlers/scst_raid.c @@ -98,7 +98,7 @@ static int raid_attach(struct scst_device *dev) /* Let's try not to be too smart and continue processing */ } - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 587903451..546731cd7 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -226,7 +226,7 @@ static int tape_attach(struct scst_device *dev) dev->block_shift = scst_calc_block_shift(dev->block_size); obtain: - res = scst_obtain_device_parameters(dev); + res = scst_obtain_device_parameters(dev, NULL); if (res != 0) { PRINT_ERROR("Failed to obtain control parameters for device " "%s", dev->virt_name); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 87a13e116..aa488c383 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -8178,11 +8178,18 @@ void scst_unblock_dev(struct scst_device *dev) /** * scst_obtain_device_parameters() - obtain device control parameters + * @dev: device to act on + * @mode_select_cdb: original MODE SELECT CDB * - * Issues a MODE SENSE for control mode page data and sets the corresponding - * dev's parameter from it. Returns 0 on success and not 0 otherwise. + * Issues a MODE SENSE for necessary pages data and sets the corresponding + * dev's parameter from it. Parameter mode_select_cdb is pointer on original + * MODE SELECT CDB, if this function called to refresh parameters after + * successfully finished MODE SELECT command detected. + * + * Returns 0 on success and not 0 otherwise. */ -int scst_obtain_device_parameters(struct scst_device *dev) +int scst_obtain_device_parameters(struct scst_device *dev, + const uint8_t *mode_select_cdb) { int rc, i; uint8_t cmd[16]; @@ -8193,6 +8200,14 @@ int scst_obtain_device_parameters(struct scst_device *dev) EXTRACHECKS_BUG_ON(dev->scsi_dev == NULL); + if (mode_select_cdb != NULL) { + if ((mode_select_cdb[2] & 0x3F) != 0x0A) { + TRACE_DBG("Not control mode page (%x) change requested, " + "skipping", mode_select_cdb[2] & 0x3F); + goto out; + } + } + for (i = 0; i < 5; i++) { /* Get control mode page */ memset(cmd, 0, sizeof(cmd)); @@ -8274,7 +8289,8 @@ int scst_obtain_device_parameters(struct scst_device *dev) SCST_SENSE_KEY_VALID, ILLEGAL_REQUEST, 0, 0)) { PRINT_INFO("Device %s doesn't support " - "MODE SENSE", dev->virt_name); + "MODE SENSE or control mode page", + dev->virt_name); break; } else if (scst_analyze_sense(sense_buffer, sizeof(sense_buffer), diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 2067d10f5..b8d99b962 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -773,8 +773,8 @@ static int scst_parse_cmd(struct scst_cmd *cmd) devt->name, cmd->tgtt->name, cmd->bufflen); PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB", cmd->cdb, cmd->cdb_len); - if ((cmd->data_direction & SCST_DATA_READ) || - (cmd->data_direction & SCST_DATA_WRITE)) + if ((cmd->expected_data_direction & SCST_DATA_READ) || + (cmd->expected_data_direction & SCST_DATA_WRITE)) cmd->resid_possible = 1; } if (unlikely(cmd->out_bufflen != cmd->expected_out_transfer_len)) { @@ -3287,7 +3287,7 @@ static int scst_mode_select_checks(struct scst_cmd *cmd) spin_unlock_bh(&dev->dev_lock); if (dev->scsi_dev != NULL) - scst_obtain_device_parameters(dev); + scst_obtain_device_parameters(dev, cmd->cdb); } } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) && scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) && @@ -3317,7 +3317,7 @@ static int scst_mode_select_checks(struct scst_cmd *cmd) "(LUN %lld): getting new parameters", cmd->sense[12], (long long unsigned int)cmd->lun); - scst_obtain_device_parameters(cmd->dev); + scst_obtain_device_parameters(cmd->dev, NULL); } else sBUG();