⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initiator_rx.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				size = related_command->SCpnt->request_bufflen					- data_in_header->offset;			else				size = 0;		} else {			/* be sure this is not negative for use later on! */			over_flow_data_size = 0;		}		if (unlikely(TRACE_TEST(TRACE_DEBUG))) {			TRACE(TRACE_DEBUG, "Local data offset %u, "			      "request length %d\n",			      related_command->data_offset,			      related_command->SCpnt->request_bufflen);			TRACE(TRACE_DEBUG,			      "DataIn hdr data offset %u, payload len %u\n",			      data_in_header->offset, size);		}		if (related_command->recvd_length == 0) {			/* this is first PDU in a sequence */			related_command->r2t_range_list.offset						= data_in_header->offset;			/* can sequences be out-of-order? */			if (unlikely(!related_session->oper_param							->DataSequenceInOrder)){				/* DataSequenceInOrder==No, so seqs can be				 * out-of-order				 */				related_command->data_offset						= data_in_header->offset;			}			/* can the PDU's within a sequence be out-of-order? */			if (unlikely(!related_session->oper_param							->DataPDUInOrder)) {				/* DataPDUInOrder==No, so PDUs can be				 * out-of-order				 */				related_command->pdu_range_list.limit = 0;				related_command->pdu_range_list.offset								= ALL_ONES;			}		}		/* can the PDU's within a sequence be out-of-order? */		if (unlikely(!related_session->oper_param->DataPDUInOrder)) {			/* DataPDUInOrder==No, so PDU can be out-of-order */			__u32 limit;			if (related_command->pdu_range_list.offset						> data_in_header->offset) {				/* this is smallest offset seen so far */				related_command->pdu_range_list.offset						= data_in_header->offset;			}			limit = data_in_header->offset + size;			if (related_command->pdu_range_list.limit < limit) {				/* this is largest limit seen so far */				related_command->pdu_range_list.limit = limit;			}			/* each DataIn PDU is its own range */			merge_offset_length(&related_command->pdu_range_list,					    data_in_header->offset, size);		} else {			/* DataPDUInOrder==Yes, so PDU must be			 * in-order within seq.			 * Does buffer offset in DataIn header have			 * expected value?			 */			if (unlikely(related_command->data_offset						!= data_in_header->offset)) {				TRACE_ERROR(					"DataIn with ITT %u, DataSN %u, size "					"%u, has offset %u, expected %u\n",					local_itt, data_in_header->data_sn,					size, data_in_header->offset,					related_command->data_offset);			}		}		if (unlikely(size == 0)) {			TRACE_WARNING("DataIn with ITT %u, DataSN %u, "				      "offset %u, has no data\n", local_itt,				      data_in_header->data_sn,				      data_in_header->offset);		} else {			received = recv_data_in_data(current_connection,						     related_command,						     data_in_header,						     &size,						     over_flow_data_size,						     &over_flow_buffer);			if (unlikely(received <= 0))				goto out;			/* data in the DataIn was received correctly,			 * update amount of data transfered so far in this seq			 */			related_command->data_offset += size;			related_command->recvd_length += size;#ifdef ISCSI_CHECK_PDU_FORMAT			/* Check that we have not received more data			 * than allowed in one input sequence			 */			if (unlikely(related_command->recvd_length				> related_session->oper_param->MaxBurstLength)){				TRACE_ERROR(					"DataIn with ITT %u gives sequence with"					" %u bytes, more than %u allowed by "					"%s\n", local_itt,					related_command->recvd_length,					related_session->oper_param						->MaxBurstLength,					"MaxBurstLength");			}#endif			/* update amount of data transfered so far in this cmd*/			related_command->r2t_range_list.limit += size;			related_command->cmd_error_size += size;			/* if this is the last DataIn PDU expected for the			 * corresponding SCSI Command, check that F_BIT is set			 */			if (related_command->r2t_range_list.limit				>= related_command->SCpnt->request_bufflen) {				/* last rexmitted DataIn PDU may not have				 * F bit set				 */				if (unlikely(!(data_in_header->flags & F_BIT)					&& related_command->cmd_error_state							!= CMD_USING_SNACK)) {					TRACE_ERROR(				 		"F_BIT not set on last expected"						" DataIn with ITT %u\n",						local_itt);					/* turn it on now */					data_in_header->flags |= F_BIT;				}			}		}		if ((data_in_header->flags & F_BIT)) {			/* this is last DataIn PDU in a sequence, set up for			 * any new sequence that may follow this one			 */			if (unlikely(!related_session->oper_param							->DataPDUInOrder)) {				/* DataPDUInOrder==No, pdus can be				 * out-of-order within a sequence				 */				check_range_list_complete(&related_command->								pdu_range_list);				free_range_list(&related_command->								pdu_range_list);				/* set up offset to first pdu in this sequence*/				related_command->r2t_range_list.offset				    = related_command->pdu_range_list.offset;			}			if (unlikely(!related_session->oper_param							->DataSequenceInOrder)){				/* DataSequenceInOrder==No, sequences can				 * be out-of-order				 */				merge_offset_length(&related_command->							r2t_range_list,						    related_command->							r2t_range_list.offset,						    related_command->							recvd_length);			} else if (unlikely(related_command					->r2t_range_list.offset						+ related_command->recvd_length				    != related_command->r2t_range_list.limit)) {				/* in-order sequence not in-order */				if (related_command->cmd_error_state							== CMD_OK_SO_FAR) {					/* avoid cascading error messages					 * during error recovery					 */					TRACE_ERROR(					    "In-order sequence started at "					    "offset %u, expected to start at "					    "%u\n",					     related_command->r2t_range_list.						offset,					     related_command->r2t_range_list.					       limit					       - related_command->recvd_length);				}			}			/* mark that next DataIn PDU (if any) starts			 * a new sequence			 */			related_command->recvd_length = 0;		}		if (unlikely(related_command->cmd_error_state							== CMD_USING_SNACK)) {			/* this DataIn is a reply to previous SNACK from us */			related_command->cmd_error_runlen -= 1;			if (related_command->cmd_error_runlen == 0) {				/* this is last DataIn from previous SNACK */				related_command->cmd_error_state=CMD_OK_SO_FAR;				/* now we can acknowledge the stat_sn if a				 * DataIn S=1 or SCSI Response originally				 * caused us to send the SNACK				 */				if (current_connection->increment) {					if (!(data_in_header->flags & S_BIT)) {					      current_connection->exp_stat_sn++;					      data_in_header->flags |= S_BIT;					}				} else {					/* make it look like this pdu was the					 * one that had the original A bit set					 * by restoring fields saved from the					 * DataIn pdu that started the rexmit					 */					data_in_header->flags |= A_BIT;					data_in_header->target_xfer_tag =						related_command->abit_ttt;					data_in_header->lun =						related_command->abit_lun;					related_command->data_in_sn =						related_command->abit_in_sn;					related_command->data_offset =						related_command->abit_offset;				}			}		}		if (unlikely((data_in_header->flags & A_BIT)			&& related_session->oper_param->ErrorRecoveryLevel>0)) {			if (related_command->cmd_error_state == CMD_OK_SO_FAR) {				/* send target the DataACK SNACK he requested */				err_rec.curr_conn = current_connection;				err_rec.related_cmd = related_command;				err_rec.err_type = -1;				received = init_send_snack(&err_rec,						related_command->data_in_sn,						0, DATACK_SNACK);				if (received <= 0)					goto out;			} else if (related_command->cmd_error_state							== CMD_NEEDS_SNACK) {				/* time to send a snack to get erroneous				 * DataIn pdus retransmitted				 */				received=send_data_ack_snack(current_connection,							    related_command, 0);				if (received <= 0)					goto out;			} else {/* should never happen */				TRACE_ERROR("got DataIN with A_BIT set but "					    "cmd_error_state %d\n",					    related_command->cmd_error_state);			}		}		if (data_in_header->flags & S_BIT) {			/* this command is a "phase collapse" with "good"			 * status or is the last DataIn pdu retransmitted			 * as part of a recovery triggered by S_BIT or			 * scsi response			 */			TRACE(TRACE_DEBUG, "Phase collapse, ITT %u, "			      "recvd_length %u, data_offset %u, "			      "request_bufflen %u, recv_so_far %u, "			      "data_in_sn %u\n", local_itt, 			      related_command->recvd_length,			      related_command->data_offset,			      related_command->SCpnt->request_bufflen,			      related_command->r2t_range_list.limit,			      related_command->data_in_sn);			received = do_scsi_response(current_connection,						related_command,						(struct iscsi_targ_scsi_rsp *)						data_in_header, 0, NULL);		}	}out:	if (unlikely(over_flow_buffer != NULL))		my_kfree((void **) &over_flow_buffer, "local buf");	TRACE(TRACE_ENTER_LEAVE, "Leave rx_data, retval %d\n", received);	return received;}static int __attribute__ ((no_instrument_function))rx_pack_cookie_from_pdu( struct session *related_session,			struct connection *current_connection,	        	struct command *related_command ,			struct iscsi_targ_r2t   *r2t_header,        		__u32 local_itt,			__u32 offset,			__u32  xfer_len);/**************************************************************************** * executed only by rx thread. * the session->sess_lock MUST be held by the calling process/thread. * Called only by iscsi_initiator_rx_thread(). * This function processes the R2T PDU and sets up the TCP buffers for the * first iSCSI DataOut PDU to be sent out to the target. It wakes up the * tx thread so that it can send DataOut PDU to the target. * Parameters: current_connection which is a ptr to the connection struct *			  where the R2T header was received. * Return Value: >0 success *		 =0 on failure, session lock is locked *		 <0 on failure, session lock is NOT locked ****************************************************************************/static intrx_r2t(struct connection *current_connection,       __u32 local_itt, struct command *related_command){	struct iscsi_targ_r2t *r2t_header;	struct session *related_session;	struct init_error_rec err_rec;	int delta, delta2, retval = 1;	__u32 r2t_sn, offset, xfer_len;	struct r2t_cookie *cookie;	TRACE(TRACE_ENTER_LEAVE, "Enter rx_r2t, current_connection %p\n",	      current_connection);	r2t_header = (struct iscsi_targ_r2t *) current_connection->rx_buf;	r2t_sn = ntohl(r2t_header->r2t_sn);	offset = ntohl(r2t_header->offset);	xfer_len = ntohl(r2t_header->xfer_len);	if (unlikely(TRACE_TEST(TRACE_DEBUG))) {		debug_print_ip(current_connection, "R2T");	}	related_session = current_connection->my_session;#ifdef ISCSI_CHECK_PDU_FORMAT	/* Check if reserved fields are zero or not */	if (unlikely(!((r2t_header->flags & ~F_BIT) == 0						&& r2t_header->rsvd2 == 0))) {		reserved_not_0("R2T");	}#endif	if (likely(related_command != NULL)) {		/* target is responding to this command, so it does not		 * need to be sent again on a retransmission		 */		related_command->cmd_state &= ~CMD_STATE_REXMIT_ORIG;		/* is this R2T the correct sequence of R2Ts for this command? */		/* Draft 20, Section 10.8.2 R2TSN		 * "R2TSN is the R2T PDU input PDU number within the command		 * identified by the Initiator Task Tag."		 */		/* new - SAI */		delta = related_command->r2t_sn - r2t_sn;		delta2 = related_command->data_offset - offset;		if (unlikely(delta != 0)) {			if (related_session->oper_param->ErrorRecoveryLevel > 0				&& delta == 1 && delta2 > 0) {				/* only one outstanding R2T supported				 * for error recovery levels > 0.				 * If an R2T seq. repeats due to				 * inherent timeout from Target				 * either due to lost or delayed				 * DataOuts, remove the old R2T				 * cookie and recreate a new one.				 * Remember to re-transmit all				 * DataOuts requested by the R2T.				 * - new 18_04 - SAI				 */				TRACE_WARNING("Recovery R2T for ITT %u has "					      "R2TSN %u, expected %u\n",					      local_itt, r2t_sn,					      related_command->r2t_sn);				if (!list_empty(&related_command->r2t_cookies)){					/* we did not send the cookie's					 * remaining xfer length					 */					cookie = list_entry(related_command							    ->r2t_cookies.next,							    struct r2t_cookie,							    link);					related_command->data_offset						-= cookie-> r2t_xfer_length;					free_r2t_cookie(current_connection,							related_command,							cookie);				}				related_command->r2t_sn--;				TRACE(TRACE_ERROR_RECOVERY,				      "Got Recovery R2T, ITT %u, "				      "R2TSN %u, offset %u, DDTL %u\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -