From 54710618be7ebc28e75d069d6a886df3e9493a29 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 8 Jun 2007 10:54:18 +0000 Subject: [PATCH] Added limit on maximum queued on a device commands git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@126 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scsi_tgt.h | 5 ++++- scst/src/scst_lib.c | 9 ++++++--- scst/src/scst_priv.h | 15 +++++++++++---- scst/src/scst_targ.c | 23 ++++++++++++++++++----- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/scst/include/scsi_tgt.h b/scst/include/scsi_tgt.h index 61e813f39..4583a9111 100644 --- a/scst/include/scsi_tgt.h +++ b/scst/include/scsi_tgt.h @@ -1184,6 +1184,9 @@ struct scst_device /* Lists of commands with the lock, if dedicated threads are used */ struct scst_cmd_lists cmd_lists; + /* How many cmds alive on this dev */ + atomic_t dev_cmd_count; + unsigned short type; /* SCSI type of the device */ /************************************************************* @@ -1283,7 +1286,7 @@ struct scst_tgt_dev lun_t lun; /* to save extra dereferences */ /* How many cmds alive on this dev in this session */ - atomic_t cmd_count; + atomic_t tgt_dev_cmd_count; int gfp_mask; struct sgv_pool *pool; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 63c5dc4f6..c2f0f062a 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -162,6 +162,7 @@ int scst_alloc_device(int gfp_mask, struct scst_device **out_dev) } dev->p_cmd_lists = &scst_main_cmd_lists; + atomic_set(&dev->dev_cmd_count, 0); spin_lock_init(&dev->dev_lock); atomic_set(&dev->on_dev_count, 0); INIT_LIST_HEAD(&dev->blocked_cmd_list); @@ -354,7 +355,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess, tgt_dev->lun = acg_dev->lun; tgt_dev->acg_dev = acg_dev; tgt_dev->sess = sess; - atomic_set(&tgt_dev->cmd_count, 0); + atomic_set(&tgt_dev->tgt_dev_cmd_count, 0); tgt_dev->gfp_mask = __GFP_NOWARN; tgt_dev->pool = &scst_sgv.norm; @@ -1211,8 +1212,10 @@ void scst_free_cmd(struct scst_cmd *cmd) } #endif - if (likely(cmd->tgt_dev != NULL)) - atomic_dec(&cmd->tgt_dev->cmd_count); + if (likely(cmd->tgt_dev != NULL)) { + atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count); + atomic_dec(&cmd->dev->dev_cmd_count); + } /* * cmd->mgmt_cmnd can't being changed here, since for that it either diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index cca7203c4..82c7d0b01 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -105,12 +105,19 @@ extern unsigned long scst_trace_flag; /** ** Maximum count of uncompleted commands that an initiator could - ** queue on any device. Then it will take TASK QUEUE FULL status. + ** queue on any device. Then it will start getting TASK QUEUE FULL status. **/ -#define SCST_MAX_DEVICE_COMMANDS 128 +#define SCST_MAX_TGT_DEV_COMMANDS 64 -#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ) -#define SCST_CMD_MEM_TIMEOUT (120*HZ) +/** + ** Maximum count of uncompleted commands that could be queued on any device. + ** Then initiators sending commands to this device will start getting + ** TASK QUEUE FULL status. + **/ +#define SCST_MAX_DEV_COMMANDS 256 + +#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ) +#define SCST_CMD_MEM_TIMEOUT (120*HZ) static inline int scst_get_context(void) { if (in_irq()) diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index f37ac72ea..65fc048ce 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2632,15 +2632,23 @@ static int __scst_init_cmd(struct scst_cmd *cmd) if (likely(res == 0)) { int cnt; cmd->state = SCST_CMD_STATE_DEV_PARSE; - cnt = atomic_inc_return(&cmd->tgt_dev->cmd_count); - if (unlikely(cnt > SCST_MAX_DEVICE_COMMANDS)) { + cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count); + if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) { TRACE(TRACE_RETRY, "Too many pending commands in " "session, returning BUSY to initiator \"%s\"", (cmd->sess->initiator_name[0] == '\0') ? "Anonymous" : cmd->sess->initiator_name); - scst_set_busy(cmd); - cmd->state = SCST_CMD_STATE_XMIT_RESP; - } else if (!cmd->no_sn) + goto out_busy; + } + cnt = atomic_inc_return(&cmd->dev->dev_cmd_count); + if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) { + TRACE(TRACE_RETRY, "Too many pending device commands, " + "returning BUSY to initiator \"%s\"", + (cmd->sess->initiator_name[0] == '\0') ? + "Anonymous" : cmd->sess->initiator_name); + goto out_busy; + } + if (!cmd->no_sn) scst_cmd_set_sn(cmd); } else if (res < 0) { TRACE_DBG("Finishing cmd %p", cmd); @@ -2653,6 +2661,11 @@ static int __scst_init_cmd(struct scst_cmd *cmd) out: TRACE_EXIT_RES(res); return res; + +out_busy: + scst_set_busy(cmd); + cmd->state = SCST_CMD_STATE_XMIT_RESP; + goto out; } /* Called under scst_init_lock and IRQs disabled */