Print this page
653 incorrect handling in iscsit of duplicate PDUs with cmdsn > expsn
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
@@ -18,14 +18,13 @@
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
-/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- */
#include <sys/cpuvar.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/stat.h>
@@ -3159,13 +3158,25 @@
}
iscsit_conn_dispatch_hold(ict);
mutex_exit(&ict->ict_mutex);
index = ntohl(cmdsn) % ISCSIT_RXPDU_QUEUE_LEN;
- ASSERT(cbuf->cb_buffer[index] == NULL);
+ /*
+ * In the normal case, assuming that the Initiator is not
+ * buggy and that we don't have packet duplication occuring,
+ * the entry in the array will be NULL. However, we may have
+ * received a duplicate PDU with cmdsn > expsn , and in that
+ * case we just ignore this PDU -- the previously received one
+ * remains queued for processing. We need to be careful not
+ * to leak this one however.
+ */
+ if (cbuf->cb_buffer[index] != NULL) {
+ idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
+ } else {
cbuf->cb_buffer[index] = rx_pdu;
cbuf->cb_num_elems++;
+ }
}
static idm_pdu_t *
iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn)
{