{
        struct kvec *iov;
        u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
-       u32 payload_length = ntoh24(hdr->dlength);
+       u32 payload_length;
        int iov_ret, data_crc_failed = 0;
 
+       payload_length = min_t(u32, cmd->se_cmd.data_length,
+                              ntoh24(hdr->dlength));
        rx_size += payload_length;
        iov = &cmd->iov_data[0];
 
        u32 checksum, iov_count = 0, padding = 0;
        struct iscsi_conn *conn = cmd->conn;
        struct kvec *iov;
+       void *overflow_buf = NULL;
 
-       iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, length);
+       BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length);
+       rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length);
+       iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done,
+                                  rx_size);
        if (iov_ret < 0)
                return IMMEDIATE_DATA_CANNOT_RECOVER;
 
-       rx_size = length;
        iov_count = iov_ret;
        iov = &cmd->iov_data[0];
+       if (rx_size < length) {
+               /*
+                * Special case: length of immediate data exceeds the data
+                * buffer size derived from the CDB.
+                */
+               overflow_buf = kmalloc(length - rx_size, GFP_KERNEL);
+               if (!overflow_buf) {
+                       iscsit_unmap_iovec(cmd);
+                       return IMMEDIATE_DATA_CANNOT_RECOVER;
+               }
+               cmd->overflow_buf = overflow_buf;
+               iov[iov_count].iov_base = overflow_buf;
+               iov[iov_count].iov_len = length - rx_size;
+               iov_count++;
+               rx_size = length;
+       }
 
        padding = ((-length) & 3);
        if (padding != 0) {