From: <rsw...@us...> - 2010-04-08 20:44:07
|
Revision: 312 http://iscsitarget.svn.sourceforge.net/iscsitarget/?rev=312&view=rev Author: rswwalker Date: 2010-04-08 20:44:00 +0000 (Thu, 08 Apr 2010) Log Message: ----------- This fixes a race condition with data-outs when running multiple connections over a session. The race exists between iscsi_session_push_cmnd() and data_out_end() for scsi_cmnd_exec() where due to the order of processing incoming data the same command could be issued twice causing an oops. The fix is relatively simple, only push() complete commands and make data_out_end() push() instead of exec() on final data-out pdus. Tested on RHEL5 with MS initiator using MC/S. Signed-off-by: Ross Walker Modified Paths: -------------- trunk/kernel/iscsi.c Modified: trunk/kernel/iscsi.c =================================================================== --- trunk/kernel/iscsi.c 2010-03-30 18:17:54 UTC (rev 311) +++ trunk/kernel/iscsi.c 2010-04-08 20:44:00 UTC (rev 312) @@ -826,15 +826,12 @@ static void scsi_cmnd_exec(struct iscsi_cmnd *cmnd) { - if (cmnd->r2t_length) { - if (!cmnd->is_unsolicited_data) - send_r2t(cmnd); + assert(!cmnd->r2t_length); + + if (cmnd->lun) { + iscsi_scsi_queuecmnd(cmnd); } else { - if (cmnd->lun) { - iscsi_scsi_queuecmnd(cmnd); - } else { - iscsi_device_queue_cmnd(cmnd); - } + iscsi_device_queue_cmnd(cmnd); } } @@ -1093,6 +1090,8 @@ return; } +static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd); + static void data_out_end(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) { struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; @@ -1116,8 +1115,7 @@ if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { if (req->flags & ISCSI_FLG_FINAL) { scsi_cmnd->is_unsolicited_data = 0; - if (!cmnd_pending(scsi_cmnd)) - scsi_cmnd_exec(scsi_cmnd); + iscsi_session_push_cmnd(scsi_cmnd); } } else { /* TODO : proper error handling */ @@ -1132,7 +1130,7 @@ if (scsi_cmnd->r2t_length == 0) assert(list_empty(&scsi_cmnd->pdu_list)); - scsi_cmnd_exec(scsi_cmnd); + iscsi_session_push_cmnd(scsi_cmnd); } out: @@ -1734,6 +1732,12 @@ struct list_head *entry; u32 cmd_sn; + if (cmnd->r2t_length) { + if (!cmnd->is_unsolicited_data) + send_r2t(cmnd); + return; + } + dprintk(D_GENERIC, "%p:%x %u,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |