30 secs (default timeout) is too long to wait for memory. For ESX we would have seen several aborts and linux will just be starting to send an abort. We would like to fail these commands with TASK SET FULL so the initaitor knows it is sendng too many commands. We do not want to use the same time out value as cmd_time_out because we may not want that set if userspace has its own timers for commands that have got ring space and made it to the userspace daemon. This adds a new tcmu timeout for this case, qfull_time-out which controls how long we wait for ring space. Signed-off-by: Mike Christie <mchristi@xxxxxxxxxx> --- drivers/target/target_core_user.c | 42 +++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index fd9fcea..7d1da43 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -145,6 +145,7 @@ struct tcmu_dev { struct timer_list timeout; unsigned int cmd_time_out; + unsigned int qfull_time_out; spinlock_t nl_cmd_lock; struct tcmu_nl_cmd curr_nl_cmd; @@ -864,12 +865,15 @@ static inline size_t tcmu_cmd_get_cmd_size(struct tcmu_cmd *tcmu_cmd, if (udev->cmd_time_out) ret = schedule_timeout( msecs_to_jiffies(udev->cmd_time_out)); + else if (udev->qfull_time_out) + ret = schedule_timeout( + msecs_to_jiffies(udev->qfull_time_out)); else ret = schedule_timeout(msecs_to_jiffies(TCMU_TIME_OUT)); finish_wait(&udev->wait_cmdr, &__wait); if (!ret) { - pr_warn("tcmu: command timed out\n"); - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + pr_warn("tcmu: command timed out waiting for ring space.\n"); + return TCM_OUT_OF_RESOURCES; } mutex_lock(&udev->cmdr_lock); @@ -1816,8 +1820,8 @@ static ssize_t tcmu_cmd_time_out_show(struct config_item *item, char *page) return snprintf(page, PAGE_SIZE, "%lu\n", udev->cmd_time_out / MSEC_PER_SEC); } -static ssize_t tcmu_cmd_time_out_store(struct config_item *item, const char *page, - size_t count) +static ssize_t tcmu_cmd_time_out_store(struct config_item *item, + const char *page, size_t count) { struct se_dev_attrib *da = container_of(to_config_group(item), struct se_dev_attrib, da_group); @@ -1840,6 +1844,35 @@ static ssize_t tcmu_cmd_time_out_store(struct config_item *item, const char *pag } CONFIGFS_ATTR(tcmu_, cmd_time_out); +static ssize_t tcmu_qfull_time_out_show(struct config_item *item, char *page) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = container_of(da->da_dev, + struct tcmu_dev, se_dev); + + return snprintf(page, PAGE_SIZE, "%lu\n", udev->qfull_time_out / MSEC_PER_SEC); +} + +static ssize_t tcmu_qfull_time_out_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = container_of(da->da_dev, + struct tcmu_dev, se_dev); + u32 val; + int ret; + + ret = kstrtou32(page, 0, &val); + if (ret < 0) + return ret; + + udev->qfull_time_out = val * MSEC_PER_SEC; + return count; +} +CONFIGFS_ATTR(tcmu_, qfull_time_out); + static ssize_t tcmu_dev_config_show(struct config_item *item, char *page) { struct se_dev_attrib *da = container_of(to_config_group(item), @@ -1956,6 +1989,7 @@ static ssize_t tcmu_emulate_write_cache_store(struct config_item *item, CONFIGFS_ATTR(tcmu_, emulate_write_cache); static struct configfs_attribute *tcmu_attrib_attrs[] = { + &tcmu_attr_qfull_time_out, &tcmu_attr_cmd_time_out, &tcmu_attr_dev_config, &tcmu_attr_dev_size, -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html