From 3a84cb7bafb2781f6d3b4833ef0ab484f28bde3a Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Sat, 16 Mar 2013 01:10:43 +0000 Subject: [PATCH] Automatic queue depth adjustment in scst_local git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4798 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 3 + scst/src/scst_lib.c | 2 + scst/src/scst_priv.h | 3 - scst_local/scst_local.c | 127 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 6 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 8add0e10d..f6825ed76 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -4472,4 +4472,7 @@ struct scst_data_descriptor { void scst_write_same(struct scst_cmd *cmd); +__be64 scst_pack_lun(const uint64_t lun, enum scst_lun_addr_method addr_method); +uint64_t scst_unpack_lun(const uint8_t *lun, int len); + #endif /* __SCST_H */ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 467fc7ab7..1f6408fa4 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -6889,6 +6889,7 @@ __be64 scst_pack_lun(const uint64_t lun, enum scst_lun_addr_method addr_method) TRACE_EXIT_HRES(res >> 48); return cpu_to_be64(res); } +EXPORT_SYMBOL(scst_pack_lun); /* * Function to extract a LUN number from an 8-byte LUN structure in network byte @@ -6951,6 +6952,7 @@ out_err: PRINT_ERROR("%s", "Multi-level LUN unimplemented"); goto out; } +EXPORT_SYMBOL(scst_unpack_lun); /** ** Generic parse() support routines. diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index bc8bb3900..58886dde9 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -391,9 +391,6 @@ int scst_alloc_space(struct scst_cmd *cmd); int scst_lib_init(void); void scst_lib_exit(void); -__be64 scst_pack_lun(const uint64_t lun, enum scst_lun_addr_method addr_method); -uint64_t scst_unpack_lun(const uint8_t *lun, int len); - struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask); void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd); void scst_done_cmd_mgmt(struct scst_cmd *cmd); diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index 326214c12..89cf53461 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -41,6 +41,10 @@ #include #endif +#ifndef RHEL_RELEASE_VERSION +#define RHEL_RELEASE_VERSION(maj, min) 0 +#endif + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) #endif @@ -870,7 +874,7 @@ static int scst_local_target_reset(struct scsi_cmnd *SCpnt) } #endif -static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd) +static void scst_local_copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd) { int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd); @@ -906,7 +910,7 @@ static int scst_local_send_resp(struct scsi_cmnd *cmnd, /* Simulate autosense by this driver */ if (unlikely(scst_sense_valid(scst_cmnd->sense))) - copy_sense(cmnd, scst_cmnd); + scst_local_copy_sense(cmnd, scst_cmnd); } cmnd->result = scsi_result; @@ -1124,6 +1128,102 @@ static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd) return res; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) || \ + defined(CONFIG_SUSE_KERNEL) || \ + !(!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(6, 1)) + +static int scst_local_get_max_queue_depth(struct scsi_device *sdev) +{ + int res; + struct scst_local_sess *sess; + __be16 lun; + + TRACE_ENTRY(); + + sess = to_scst_lcl_sess(scsi_get_device(sdev->host)); + lun = cpu_to_be16(sdev->lun); + res = scst_get_max_lun_commands(sess->scst_sess, + scst_unpack_lun((const uint8_t *)&lun, sizeof(lun))); + + TRACE_EXIT_RES(res); + return res; +} + +static int scst_local_change_queue_depth(struct scsi_device *sdev, int depth, + int reason) +{ + int res, mqd; + + TRACE_ENTRY(); + + switch (reason) { + case SCSI_QDEPTH_DEFAULT: + mqd = scst_local_get_max_queue_depth(sdev); + if (mqd < depth) { + PRINT_INFO("Requested queue depth %d is too big " + "(possible max %d (sdev %p)", depth, mqd, sdev); + res = -EINVAL; + goto out; + } + + PRINT_INFO("Setting queue depth %d as default (sdev %p, " + "current %d)", depth, sdev, sdev->queue_depth); + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + break; + + case SCSI_QDEPTH_QFULL: + TRACE(TRACE_FLOW_CONTROL, "QUEUE FULL on sdev %p, setting " + "qdepth %d (cur %d)", sdev, depth, sdev->queue_depth); + scsi_track_queue_full(sdev, depth); + break; + + case SCSI_QDEPTH_RAMP_UP: + TRACE(TRACE_FLOW_CONTROL, "Ramping up qdepth on sdev %p to %d " + "(cur %d)", sdev, depth, sdev->queue_depth); + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + break; + + default: + res = -EOPNOTSUPP; + goto out; + } + + res = sdev->queue_depth; + +out: + TRACE_EXIT_RES(res); + return res; +} + +static int scst_local_slave_alloc(struct scsi_device *sdev) +{ + queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdev->request_queue); + return 0; +} + +static int scst_local_slave_configure(struct scsi_device *sdev) +{ + int mqd; + + TRACE_ENTRY(); + + mqd = scst_local_get_max_queue_depth(sdev); + + PRINT_INFO("Configuring queue depth %d on sdev %p (tagged supported %d)", + mqd, sdev, sdev->tagged_supported); + + if (sdev->tagged_supported) + scsi_activate_tcq(sdev, mqd); + else + scsi_deactivate_tcq(sdev, mqd); + + TRACE_EXIT(); + return 0; +} + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && !defined(CONFIG_SUSE_KERNEL) && (!defined(RHEL_RELEASE_CODE) || RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(6, 1)) */ + /* Must be called under sess->aen_lock. Drops then reacquires it inside. */ static void scst_process_aens(struct scst_local_sess *sess, bool cleanup_only) @@ -1426,16 +1526,37 @@ static struct scsi_host_template scst_lcl_ini_driver_template = { .queuecommand = scst_local_queuecommand_lck, #else .queuecommand = scst_local_queuecommand, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) || \ + defined(CONFIG_SUSE_KERNEL) || \ + !(!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(6, 1)) + .change_queue_depth = scst_local_change_queue_depth, + .slave_alloc = scst_local_slave_alloc, + .slave_configure = scst_local_slave_configure, #endif .eh_abort_handler = scst_local_abort, .eh_device_reset_handler = scst_local_device_reset, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)) .eh_target_reset_handler = scst_local_target_reset, #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) || \ + defined(CONFIG_SUSE_KERNEL) || \ + !(!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(6, 1)) + .can_queue = 2048, + /* + * Set it low for the "Drop back to untagged" case in + * scsi_track_queue_full(). We are adjusting it to a better + * default in slave_configure() + */ + .cmd_per_lun = 3, +#else .can_queue = 256, + .cmd_per_lun = 32, +#endif .this_id = -1, .sg_tablesize = 0xFFFF, - .cmd_per_lun = 32, .max_sectors = 0xffff, /* Possible pass-through backend device may not support clustering */ .use_clustering = DISABLE_CLUSTERING,