mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-21 06:36:27 +00:00
Uniform max queue depth handling in iSCSI
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1556 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1004,6 +1004,7 @@ static int iscsi_register(void __user *arg)
|
||||
|
||||
memset(®, 0, sizeof(reg));
|
||||
reg.max_data_seg_len = ISCSI_CONN_IOV_MAX << PAGE_SHIFT;
|
||||
reg.max_queued_cmds = scst_get_max_lun_commands(NULL, NO_SUCH_LUN);
|
||||
|
||||
res = 0;
|
||||
|
||||
|
||||
@@ -473,7 +473,7 @@ static void conn_nop_in_delayed_work_fn(struct delayed_work *work)
|
||||
}
|
||||
|
||||
if (conn->nop_in_interval > 0) {
|
||||
TRACE_DBG("Reschedule NOP-In work for conn %p", conn);
|
||||
TRACE_DBG("Reschedule Nop-In work for conn %p", conn);
|
||||
schedule_delayed_work(&conn->nop_in_delayed_work,
|
||||
conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
|
||||
}
|
||||
@@ -755,7 +755,7 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
|
||||
conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
|
||||
conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
|
||||
if (conn->nop_in_interval > 0) {
|
||||
TRACE_DBG("Schedule NOP-In work for conn %p", conn);
|
||||
TRACE_DBG("Schedule Nop-In work for conn %p", conn);
|
||||
schedule_delayed_work(&conn->nop_in_delayed_work,
|
||||
conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
|
||||
}
|
||||
|
||||
@@ -1558,7 +1558,7 @@ static int nop_out_start(struct iscsi_cmnd *cmnd)
|
||||
iscsi_extracheck_is_rd_thread(conn);
|
||||
|
||||
if (!(req_hdr->flags & ISCSI_FLG_FINAL)) {
|
||||
PRINT_ERROR("%s", "Initiator sent NOP-Out with not a single "
|
||||
PRINT_ERROR("%s", "Initiator sent Nop-Out with not a single "
|
||||
"PDU");
|
||||
err = -ISCSI_REASON_PROTOCOL_ERROR;
|
||||
goto out;
|
||||
@@ -1567,7 +1567,7 @@ static int nop_out_start(struct iscsi_cmnd *cmnd)
|
||||
if (cmnd_itt(cmnd) == cpu_to_be32(ISCSI_RESERVED_TAG)) {
|
||||
if (unlikely(!(cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE)))
|
||||
PRINT_ERROR("%s", "Initiator sent RESERVED tag for "
|
||||
"non-immediate NOP-Out command");
|
||||
"non-immediate Nop-Out command");
|
||||
}
|
||||
|
||||
spin_lock(&conn->session->sn_lock);
|
||||
@@ -1588,7 +1588,7 @@ static int nop_out_start(struct iscsi_cmnd *cmnd)
|
||||
&cmnd->sg_cnt);
|
||||
if (sg == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Allocating buffer for"
|
||||
" %d NOP-Out payload failed", size);
|
||||
" %d Nop-Out payload failed", size);
|
||||
err = -ISCSI_REASON_OUT_OF_RESOURCES;
|
||||
goto out;
|
||||
}
|
||||
@@ -2509,7 +2509,7 @@ static void nop_out_exec(struct iscsi_cmnd *req)
|
||||
struct iscsi_cmnd *r;
|
||||
struct iscsi_conn *conn = req->conn;
|
||||
|
||||
TRACE_DBG("Receive NOP-in response (ttt 0x%08x)",
|
||||
TRACE_DBG("Receive Nop-In response (ttt 0x%08x)",
|
||||
be32_to_cpu(cmnd_ttt(req)));
|
||||
|
||||
spin_lock_bh(&conn->nop_req_list_lock);
|
||||
@@ -2526,8 +2526,8 @@ static void nop_out_exec(struct iscsi_cmnd *req)
|
||||
if (found)
|
||||
cmnd_put(r);
|
||||
else
|
||||
TRACE_MGMT_DBG("%s", "Got NOP-out response without "
|
||||
"corresponding NOP-in request");
|
||||
TRACE_MGMT_DBG("%s", "Got Nop-out response without "
|
||||
"corresponding Nop-In request");
|
||||
}
|
||||
|
||||
req_cmnd_release(req);
|
||||
@@ -3489,13 +3489,13 @@ void iscsi_send_nop_in(struct iscsi_conn *conn)
|
||||
|
||||
req = cmnd_alloc(conn, NULL);
|
||||
if (req == NULL) {
|
||||
PRINT_ERROR("%s", "Unable to alloc fake NOP-IN request");
|
||||
PRINT_ERROR("%s", "Unable to alloc fake Nop-In request");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rsp = iscsi_alloc_main_rsp(req);
|
||||
if (rsp == NULL) {
|
||||
PRINT_ERROR("%s", "Unable to alloc NOP-IN rsp");
|
||||
PRINT_ERROR("%s", "Unable to alloc Nop-In rsp");
|
||||
goto out_err_free_req;
|
||||
}
|
||||
|
||||
@@ -3512,7 +3512,7 @@ void iscsi_send_nop_in(struct iscsi_conn *conn)
|
||||
|
||||
/* Supposed that all other fields are zeroed */
|
||||
|
||||
TRACE_DBG("Sending NOP-in request (ttt 0x%08x)", rsp_hdr->ttt);
|
||||
TRACE_DBG("Sending Nop-In request (ttt 0x%08x)", rsp_hdr->ttt);
|
||||
spin_lock_bh(&conn->nop_req_list_lock);
|
||||
list_add_tail(&rsp->nop_req_list_entry, &conn->nop_req_list);
|
||||
spin_unlock_bh(&conn->nop_req_list_lock);
|
||||
|
||||
@@ -767,7 +767,7 @@ static int iscsi_rx_check_ddigest(struct iscsi_conn *conn)
|
||||
cmnd_get(cmnd);
|
||||
} else if (cmnd_opcode(cmnd) != ISCSI_OP_SCSI_DATA_OUT) {
|
||||
/*
|
||||
* We could get here only for NOP-Out. ISCSI RFC
|
||||
* We could get here only for Nop-Out. ISCSI RFC
|
||||
* doesn't specify how to deal with digest errors in
|
||||
* this case. Is closing connection correct?
|
||||
*/
|
||||
|
||||
@@ -22,12 +22,17 @@ do { \
|
||||
TRACE_DBG("%s: %u", #word, (iparams)[key_##word]); \
|
||||
if ((iparams)[key_##word] < (min) || \
|
||||
(iparams)[key_##word] > (max)) { \
|
||||
PRINT_ERROR("%s: %u is out of range (%u %u)", \
|
||||
#word, (iparams)[key_##word], (min), (max)); \
|
||||
if ((iparams)[key_##word] < (min)) \
|
||||
if ((iparams)[key_##word] < (min)) { \
|
||||
(iparams)[key_##word] = (min); \
|
||||
else \
|
||||
PRINT_WARNING("%s: %u is too small, resetting " \
|
||||
"it to allowed min %u", \
|
||||
#word, (iparams)[key_##word], (min)); \
|
||||
} else { \
|
||||
PRINT_WARNING("%s: %u is too big, resetting " \
|
||||
"it to allowed max %u", \
|
||||
#word, (iparams)[key_##word], (max)); \
|
||||
(iparams)[key_##word] = (max); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -186,12 +191,14 @@ static void sess_params_get(struct iscsi_sess_params *params,
|
||||
}
|
||||
|
||||
/* target_mutex supposed to be locked */
|
||||
static void tgt_params_check(struct iscsi_kern_params_info *info)
|
||||
static void tgt_params_check(struct iscsi_session *session,
|
||||
struct iscsi_kern_params_info *info)
|
||||
{
|
||||
int32_t *iparams = info->target_params;
|
||||
|
||||
CHECK_PARAM(info, iparams, queued_cmnds, MIN_NR_QUEUED_CMNDS,
|
||||
MAX_NR_QUEUED_CMNDS);
|
||||
min_t(int, MAX_NR_QUEUED_CMNDS,
|
||||
scst_get_max_lun_commands(session->scst_sess, NO_SUCH_LUN)));
|
||||
CHECK_PARAM(info, iparams, rsp_timeout, MIN_RSP_TIMEOUT,
|
||||
MAX_RSP_TIMEOUT);
|
||||
CHECK_PARAM(info, iparams, nop_in_interval, MIN_NOP_IN_INTERVAL,
|
||||
@@ -209,14 +216,14 @@ static int iscsi_tgt_params_set(struct iscsi_session *session,
|
||||
if (set) {
|
||||
struct iscsi_conn *conn;
|
||||
|
||||
tgt_params_check(info);
|
||||
tgt_params_check(session, info);
|
||||
|
||||
SET_PARAM(params, info, iparams, queued_cmnds);
|
||||
SET_PARAM(params, info, iparams, rsp_timeout);
|
||||
SET_PARAM(params, info, iparams, nop_in_interval);
|
||||
|
||||
PRINT_INFO("Target parameters set for session %llx: "
|
||||
"QueuedCommands %d, Response timeout %d, NOP-in "
|
||||
"QueuedCommands %d, Response timeout %d, Nop-In "
|
||||
"interval %d", session->sid, params->queued_cmnds,
|
||||
params->rsp_timeout, params->nop_in_interval);
|
||||
|
||||
@@ -226,7 +233,7 @@ static int iscsi_tgt_params_set(struct iscsi_session *session,
|
||||
conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
|
||||
spin_lock_bh(&iscsi_rd_lock);
|
||||
if (!conn->closing && (conn->nop_in_interval > 0)) {
|
||||
TRACE_DBG("Schedule NOP-In work for conn %p", conn);
|
||||
TRACE_DBG("Schedule Nop-In work for conn %p", conn);
|
||||
schedule_delayed_work(&conn->nop_in_delayed_work,
|
||||
conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#define CTL_DEVICE "/dev/iscsi-scst-ctl"
|
||||
|
||||
int kernel_open(int *max_data_seg_len)
|
||||
int kernel_open(void)
|
||||
{
|
||||
FILE *f;
|
||||
char devname[256];
|
||||
@@ -91,8 +91,10 @@ int kernel_open(int *max_data_seg_len)
|
||||
"kernel module?\n", strerror(errno));
|
||||
goto out_close;
|
||||
} else {
|
||||
log_debug(0, "MAX_DATA_SEG_LEN %d", err);
|
||||
*max_data_seg_len = reg.max_data_seg_len;
|
||||
log_debug(0, "max_data_seg_len %d, max_queued_cmds %d, ",
|
||||
reg.max_data_seg_len, reg.max_queued_cmds);
|
||||
iscsi_init_params.max_data_seg_len = reg.max_data_seg_len;
|
||||
iscsi_init_params.max_queued_cmds = reg.max_queued_cmds;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -62,6 +62,8 @@ static int incoming_cnt;
|
||||
int ctrl_fd, ipc_fd, nl_fd;
|
||||
int conn_blocked;
|
||||
|
||||
struct iscsi_init_params iscsi_init_params;
|
||||
|
||||
static char program_name[] = "iscsi-scstd";
|
||||
|
||||
static struct option const long_options[] =
|
||||
@@ -566,7 +568,7 @@ static void event_loop(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void init_max_data_seg_len(int max_data_seg_len)
|
||||
static void init_max_params(void)
|
||||
{
|
||||
if ((session_keys[key_max_recv_data_length].local_def != -1) ||
|
||||
(session_keys[key_max_recv_data_length].max != -1) ||
|
||||
@@ -580,21 +582,29 @@ static void init_max_data_seg_len(int max_data_seg_len)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* QueuedCommands */
|
||||
target_keys[key_queued_cmnds].local_def = min(target_keys[key_queued_cmnds].local_def,
|
||||
iscsi_init_params.max_queued_cmds);
|
||||
target_keys[key_queued_cmnds].max = min(target_keys[key_queued_cmnds].max,
|
||||
iscsi_init_params.max_queued_cmds);
|
||||
target_keys[key_queued_cmnds].min = min(target_keys[key_queued_cmnds].min,
|
||||
iscsi_init_params.max_queued_cmds);
|
||||
|
||||
/* MaxRecvDataSegmentLength */
|
||||
session_keys[key_max_recv_data_length].local_def = max_data_seg_len;
|
||||
session_keys[key_max_recv_data_length].max = max_data_seg_len;
|
||||
session_keys[key_max_recv_data_length].local_def = iscsi_init_params.max_data_seg_len;
|
||||
session_keys[key_max_recv_data_length].max = iscsi_init_params.max_data_seg_len;
|
||||
|
||||
/* MaxXmitDataSegmentLength */
|
||||
session_keys[key_max_xmit_data_length].local_def = max_data_seg_len;
|
||||
session_keys[key_max_xmit_data_length].max = max_data_seg_len;
|
||||
session_keys[key_max_xmit_data_length].local_def = iscsi_init_params.max_data_seg_len;
|
||||
session_keys[key_max_xmit_data_length].max = iscsi_init_params.max_data_seg_len;
|
||||
|
||||
/* MaxBurstLength */
|
||||
session_keys[key_max_burst_length].local_def = max_data_seg_len;
|
||||
session_keys[key_max_burst_length].max = max_data_seg_len;
|
||||
session_keys[key_max_burst_length].local_def = iscsi_init_params.max_data_seg_len;
|
||||
session_keys[key_max_burst_length].max = iscsi_init_params.max_data_seg_len;
|
||||
|
||||
/* FirstBurstLength */
|
||||
session_keys[key_first_burst_length].local_def = max_data_seg_len;
|
||||
session_keys[key_first_burst_length].max = max_data_seg_len;
|
||||
session_keys[key_first_burst_length].local_def = iscsi_init_params.max_data_seg_len;
|
||||
session_keys[key_first_burst_length].max = iscsi_init_params.max_data_seg_len;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -605,7 +615,6 @@ int main(int argc, char **argv)
|
||||
char *config = NULL;
|
||||
uid_t uid = 0;
|
||||
gid_t gid = 0;
|
||||
int max_data_seg_len = -1;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -668,10 +677,10 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
};
|
||||
|
||||
if ((ctrl_fd = kernel_open(&max_data_seg_len)) < 0)
|
||||
if ((ctrl_fd = kernel_open()) < 0)
|
||||
exit(-1);
|
||||
|
||||
init_max_data_seg_len(max_data_seg_len);
|
||||
init_max_params();
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
err = kernel_attr_add(NULL, ISCSI_ISNS_SERVER_PARAM_NAME,
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
#define sBUG() assert(0)
|
||||
#define sBUG_ON(p) assert(!(p))
|
||||
|
||||
struct iscsi_init_params {
|
||||
int max_data_seg_len;
|
||||
int max_queued_cmds;
|
||||
};
|
||||
|
||||
struct buf_segment {
|
||||
struct __qelem entry;
|
||||
|
||||
@@ -199,6 +204,7 @@ extern void conn_free_rsp_buf_list(struct connection *conn);
|
||||
|
||||
/* iscsi_scstd.c */
|
||||
extern uint16_t server_port;
|
||||
extern struct iscsi_init_params iscsi_init_params;
|
||||
extern void isns_set_fd(int isns, int scn_listen, int scn);
|
||||
|
||||
/* iscsid.c */
|
||||
@@ -253,7 +259,7 @@ extern int iscsi_adm_request_listen(void);
|
||||
extern int iscsi_adm_request_handle(int accept_fd);
|
||||
|
||||
/* ctldev.c */
|
||||
extern int kernel_open(int *max_data_seg_len);
|
||||
extern int kernel_open(void);
|
||||
extern int kernel_params_get(u32 tid, u64 sid, int type, struct iscsi_param *params);
|
||||
extern int kernel_params_set(u32 tid, u64 sid, int type, u32 partial,
|
||||
const struct iscsi_param *params);
|
||||
|
||||
@@ -3638,6 +3638,18 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
|
||||
*/
|
||||
int scst_obtain_device_parameters(struct scst_device *dev);
|
||||
|
||||
/*
|
||||
* Returns maximum commands count which can be queued to this LUN in this
|
||||
* session.
|
||||
*
|
||||
* If lun is NO_SUCH_LUN, returns minimum of maximum commands count which
|
||||
* can be queued to any LUN in this session.
|
||||
*
|
||||
* If sess is NULL, returns minimum of maximum commands count which can be
|
||||
* queued to any SCST device.
|
||||
*/
|
||||
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
|
||||
|
||||
/*
|
||||
* Has to be put here open coded, because Linux doesn't have equivalent, which
|
||||
* allows exclusive wake ups of threads in LIFO order. We need it to let (yet)
|
||||
|
||||
@@ -5826,6 +5826,12 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun)
|
||||
{
|
||||
return SCST_MAX_TGT_DEV_COMMANDS;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get_max_lun_commands);
|
||||
|
||||
char *scst_get_next_lexem(char **token_str)
|
||||
{
|
||||
char *p = *token_str;
|
||||
|
||||
Reference in New Issue
Block a user