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)
 {