diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index d6040f62f..3e112b270 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -650,6 +650,7 @@ again: TRACE_MGMT_DBG("Unabort not yet received cmnd %p", cmnd); clear_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags); + continue; } else if (cmnd->scst_state == ISCSI_CMD_STATE_RX_CMD) { TRACE_MGMT_DBG("Aborted cmnd %p is RX_CMD, " "keep waiting", cmnd); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 7f0b24636..76fc7f6b9 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -838,7 +838,21 @@ static int process_read_io(struct iscsi_conn *conn, int *closed) case RX_BHS: res = do_recv(conn); if (res == 0) { + /* + * Clear aborted status if this command was + * accidentally aborted with other commands of + * this connection. This command not yet + * received on the aborted time, so shouldn't be + * affected by the abort. + */ + if (cmnd->prelim_compl_flags != 0) + TRACE_MGMT_DBG("Unabort not yet " + "received cmnd %p (flags %lx)", + cmnd, cmnd->prelim_compl_flags); + cmnd->prelim_compl_flags = 0; + iscsi_cmnd_get_length(&cmnd->pdu); + if (cmnd->pdu.ahssize == 0) { if ((conn->hdigest_type & DIGEST_NONE) == 0) conn->read_state = RX_INIT_HDIGEST; @@ -1224,6 +1238,15 @@ void req_add_to_write_timeout_list(struct iscsi_cmnd *req) list_add_tail(&req->write_timeout_list_entry, &conn->write_timeout_list); } + + /* We suppose that nop_in_timeout must be <= data_rsp_timeout */ + req_tt += ISCSI_ADD_SCHED_TIME; + if (timer_pending(&conn->rsp_timer) && + time_after(conn->rsp_timer.expires, req_tt)) { + TRACE_DBG("Timer adjusted for sooner expired NOP IN " + "req %p", req); + mod_timer(&conn->rsp_timer, req_tt); + } } else list_add_tail(&req->write_timeout_list_entry, &conn->write_timeout_list); diff --git a/iscsi-scst/kernel/param.c b/iscsi-scst/kernel/param.c index 65dce7be8..e61fe928f 100644 --- a/iscsi-scst/kernel/param.c +++ b/iscsi-scst/kernel/param.c @@ -115,6 +115,11 @@ static void sess_params_check(struct iscsi_kern_params_info *info) int32_t *iparams = info->session_params; const int max_len = ISCSI_CONN_IOV_MAX * PAGE_SIZE; + /* + * This is only kernel sanity check. Actual data validity checks + * performed in the user space. + */ + CHECK_PARAM(info, iparams, initial_r2t, 0, 1); CHECK_PARAM(info, iparams, immediate_data, 0, 1); CHECK_PARAM(info, iparams, max_connections, 1, 1); @@ -196,6 +201,12 @@ static void tgt_params_check(struct iscsi_session *session, struct iscsi_kern_params_info *info) { int32_t *iparams = info->target_params; + unsigned int rsp_timeout, nop_in_timeout; + + /* + * This is only kernel sanity check. Actual data validity checks + * performed in the user space. + */ CHECK_PARAM(info, iparams, queued_cmnds, MIN_NR_QUEUED_CMNDS, min_t(int, MAX_NR_QUEUED_CMNDS, @@ -206,6 +217,24 @@ static void tgt_params_check(struct iscsi_session *session, MAX_NOP_IN_INTERVAL); CHECK_PARAM(info, iparams, nop_in_timeout, MIN_NOP_IN_TIMEOUT, MAX_NOP_IN_TIMEOUT); + + /* + * We adjust too long timeout in req_add_to_write_timeout_list() + * only for NOPs, so check and warn if this assumption isn't honored. + */ + if (!info->partial || (info->partial & 1 << key_rsp_timeout)) + rsp_timeout = iparams[key_rsp_timeout]; + else + rsp_timeout = session->tgt_params.rsp_timeout; + if (!info->partial || (info->partial & 1 << key_nop_in_timeout)) + nop_in_timeout = iparams[key_nop_in_timeout]; + else + nop_in_timeout = session->tgt_params.nop_in_timeout; + if (nop_in_timeout > rsp_timeout) + PRINT_WARNING("%s", "RspTimeout should be >= NopInTimeout, " + "otherwise data transfer failure could take up to " + "NopInTimeout long to detect"); + return; } diff --git a/iscsi-scst/usr/config.c b/iscsi-scst/usr/config.c index 95ba23558..2e7c3349d 100644 --- a/iscsi-scst/usr/config.c +++ b/iscsi-scst/usr/config.c @@ -815,7 +815,7 @@ int config_params_get(u32 tid, u64 sid, int type, struct iscsi_param *params) params[i].val = target->session_params[i]; } else { for (i = 0; i < target_key_last; i++) - params[i].val = target->target_params[i]; + params[i].val = target->target_params[i]; } out: diff --git a/iscsi-scst/usr/event.c b/iscsi-scst/usr/event.c index 53c7d0f13..1f103cda7 100644 --- a/iscsi-scst/usr/event.c +++ b/iscsi-scst/usr/event.c @@ -979,6 +979,8 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event) int rc; list_for_each_entry(t, &targets_list, tlist) { + if (!t->tgt_enabled) + continue; rc = isns_target_register(t->name); if (rc < 0) { /* @@ -1080,8 +1082,10 @@ retry: } else rc = 0; rc |= send_mgmt_cmd_res(event.tid, event.cookie, E_ENABLE_TARGET, rc, NULL); - if (rc == 0) + if (rc == 0) { target->tgt_enabled = 1; + isns_target_register(target->name); + } break; case E_DISABLE_TARGET: @@ -1092,8 +1096,10 @@ retry: } else rc = 0; rc |= send_mgmt_cmd_res(event.tid, event.cookie, E_DISABLE_TARGET, rc, NULL); - if (rc == 0) + if (rc == 0) { target->tgt_enabled = 0; + isns_target_deregister(target->name); + } break; case E_GET_ATTR_VALUE: diff --git a/iscsi-scst/usr/target.c b/iscsi-scst/usr/target.c index e118ebdaf..63afb23f5 100644 --- a/iscsi-scst/usr/target.c +++ b/iscsi-scst/usr/target.c @@ -349,7 +349,8 @@ int target_del(u32 tid, u32 cookie) exit(-1); } - isns_target_deregister(target->name); + if (target->tgt_enabled) + isns_target_deregister(target->name); target_free(target); @@ -421,7 +422,9 @@ int target_add(struct target *target, u32 *tid, u32 cookie) #endif list_add_tail(&target->tlist, &targets_list); +#ifdef CONFIG_SCST_PROC isns_target_register(target->name); +#endif out: return err;