- Fixed minor problem in iSCSI-SCST

- Important reference counting and barriers usage cleanups
 - Sense buffer made dynamic
 - Other minor improvements and cleanups
 - Docs updates


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@287 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2008-02-13 17:15:47 +00:00
parent f657ae2e93
commit eec2a571dd
21 changed files with 1715 additions and 237 deletions
+32 -17
View File
@@ -454,12 +454,14 @@ static struct iscsi_cmnd *iscsi_cmnd_create_rsp_cmnd(struct iscsi_cmnd *parent)
static inline struct iscsi_cmnd *get_rsp_cmnd(struct iscsi_cmnd *req)
{
struct iscsi_cmnd *res;
struct iscsi_cmnd *res = NULL;
/* Currently this lock isn't needed, but just in case.. */
spin_lock_bh(&req->rsp_cmd_lock);
res = list_entry(req->rsp_cmd_list.prev, struct iscsi_cmnd,
rsp_cmd_list_entry);
if (!list_empty(&req->rsp_cmd_list)) {
res = list_entry(req->rsp_cmd_list.prev, struct iscsi_cmnd,
rsp_cmd_list_entry);
}
spin_unlock_bh(&req->rsp_cmd_lock);
return res;
@@ -472,6 +474,8 @@ static void iscsi_cmnds_init_write(struct list_head *send, int flags)
struct iscsi_conn *conn = rsp->conn;
struct list_head *pos, *next;
sBUG_ON(list_empty(send));
/*
* If we don't remove hashed req cmd from the hash list here, before
* submitting it for transmittion, we will have a race, when for
@@ -618,8 +622,8 @@ static struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req, int status,
rsp_hdr->cmd_status = status;
rsp_hdr->itt = cmnd_hdr(req)->itt;
if (status == SAM_STAT_CHECK_CONDITION) {
TRACE_DBG("%s", "CHECK_CONDITION");
if (SCST_SENSE_VALID(sense_buf)) {
TRACE_DBG("%s", "SENSE VALID");
/* ToDo: __GFP_NOFAIL ?? */
sg = rsp->sg = scst_alloc(PAGE_SIZE, GFP_KERNEL|__GFP_NOFAIL,
&rsp->sg_cnt);
@@ -920,11 +924,12 @@ static void cmnd_prepare_skip_pdu_set_resid(struct iscsi_cmnd *req)
TRACE_DBG("%p", req);
rsp = get_rsp_cmnd(req);
if (rsp == NULL)
goto skip;
rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
if (unlikely(cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP)) {
PRINT_ERROR("Unexpected response command %u", cmnd_opcode(rsp));
return;
}
sBUG_ON(cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP);
size = cmnd_write_size(req);
if (size) {
@@ -941,6 +946,8 @@ static void cmnd_prepare_skip_pdu_set_resid(struct iscsi_cmnd *req)
rsp_hdr->residual_count = cpu_to_be32(size);
}
}
skip:
req->pdu.bhs.opcode =
(req->pdu.bhs.opcode & ~ISCSI_OPCODE_MASK) | ISCSI_OP_SCSI_REJECT;
@@ -1285,7 +1292,6 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
if (unlikely(req->scst_state != ISCSI_CMD_STATE_AFTER_PREPROC)) {
TRACE_DBG("req %p is in %x state", req, req->scst_state);
if (req->scst_state == ISCSI_CMD_STATE_PROCESSED) {
/* Response is already prepared */
cmnd_prepare_skip_pdu_set_resid(req);
goto out;
}
@@ -1437,7 +1443,8 @@ static void data_out_end(struct iscsi_cmnd *cmnd)
iscsi_extracheck_is_rd_thread(cmnd->conn);
if (!(cmnd->conn->ddigest_type & DIGEST_NONE)) {
if (!(cmnd->conn->ddigest_type & DIGEST_NONE) &&
!cmnd->ddigest_checked) {
cmd_add_on_rx_ddigest_list(req, cmnd);
cmnd_get(cmnd);
}
@@ -1900,12 +1907,16 @@ static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd)
logout_exec(cmnd);
break;
case ISCSI_OP_SCSI_REJECT:
TRACE_MGMT_DBG("REJECT cmnd %p (scst_cmd %p)", cmnd,
cmnd->scst_cmd);
iscsi_cmnd_init_write(get_rsp_cmnd(cmnd),
ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
{
struct iscsi_cmnd *rsp = get_rsp_cmnd(cmnd);
TRACE_MGMT_DBG("REJECT cmnd %p (scst_cmd %p), rsp %p", cmnd,
cmnd->scst_cmd, rsp);
if (rsp != NULL)
iscsi_cmnd_init_write(rsp, ISCSI_INIT_WRITE_REMOVE_HASH |
ISCSI_INIT_WRITE_WAKE);
req_cmnd_release(cmnd);
break;
}
default:
PRINT_ERROR("unexpected cmnd op %x", cmnd_opcode(cmnd));
req_cmnd_release(cmnd);
@@ -2281,10 +2292,14 @@ void cmnd_rx_end(struct iscsi_cmnd *cmnd)
data_out_end(cmnd);
break;
case ISCSI_OP_PDU_REJECT:
iscsi_cmnd_init_write(get_rsp_cmnd(cmnd),
ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
{
struct iscsi_cmnd *rsp = get_rsp_cmnd(cmnd);
if (rsp != NULL)
iscsi_cmnd_init_write(rsp, ISCSI_INIT_WRITE_REMOVE_HASH |
ISCSI_INIT_WRITE_WAKE);
req_cmnd_release(cmnd);
break;
}
case ISCSI_OP_DATA_REJECT:
req_cmnd_release(cmnd);
break;
+1
View File
@@ -237,6 +237,7 @@ struct iscsi_cmnd {
unsigned int data_waiting:1;
unsigned int force_cleanup_done:1;
unsigned int dec_active_cmnds:1;
unsigned int ddigest_checked:1;
#ifdef EXTRACHECKS
unsigned int on_rx_digest_list:1;
unsigned int release_called:1;
+14 -4
View File
@@ -622,7 +622,17 @@ static int recv(struct iscsi_conn *conn)
break;
case RX_CHECK_DDIGEST:
conn->read_state = RX_END;
if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
if (cmnd->pdu.datasize <= 16*1024) {
/* It's cache hot, so let's compute it inline */
TRACE_DBG("cmnd %p, opcode %x: checking RX "
"ddigest inline", cmnd, cmnd_opcode(cmnd));
cmnd->ddigest_checked = 1;
rc = digest_rx_data(cmnd);
if (unlikely(rc != 0)) {
mark_conn_closed(conn);
goto out;
}
} else if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
cmd_add_on_rx_ddigest_list(cmnd, cmnd);
cmnd_get(cmnd);
} else if (cmnd_opcode(cmnd) != ISCSI_OP_SCSI_DATA_OUT) {
@@ -631,12 +641,12 @@ static int recv(struct iscsi_conn *conn)
* specify how to deal with digest errors in this case.
* Is closing connection correct?
*/
TRACE_DBG("cmnd %p, opcode %x: checking RX "
"ddigest inline", cmnd, cmnd_opcode(cmnd));
TRACE_DBG("cmnd %p, opcode %x: checking NOP RX "
"ddigest", cmnd, cmnd_opcode(cmnd));
rc = digest_rx_data(cmnd);
if (unlikely(rc != 0)) {
conn->read_state = RX_CHECK_DDIGEST;
mark_conn_closed(conn);
goto out;
}
}
break;