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

📄 initiator_rx.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				      local_itt, r2t_sn, offset, xfer_len);			} else {				TRACE_ERROR				    ("R2T for ITT %u has R2TSN %u, expected "				     "%u\n",				     local_itt, r2t_sn,				     related_command->r2t_sn);				TRACE(TRACE_ERROR_RECOVERY,				      "expected offset %u, tot len %u\n",				      related_command->data_offset,				      related_command->SCpnt->request_bufflen);				if (unlikely(TRACE_TEST(TRACE_ERROR_RECOVERY)))					print_targ_r2t(r2t_header);				/* R2TSN Sequence Error Recovery - SAI */				err_rec.curr_conn = current_connection;				err_rec.related_cmd = related_command;				err_rec.err_type = SEQUENCE_ERR;				retval = init_do_error_recovery(&err_rec);				goto rx_r2t_out;			}		}		related_command->r2t_sn++;		/* Draft 20, Section 10.7.4 Target Transfer Tag and LUN		 * "The Target Transfer Tag values are not specified by		 * this protocol except that the value 0xffffffff is		 * reserved and means that the Target Transfer Tag is		 * not supplied."		 */		if (unlikely(r2t_header->target_xfer_tag == ALL_ONES)) {			TRACE_ERROR("R2T has reserved TTT value 0x%08x\n",				    r2t_header->target_xfer_tag);		}		if (unlikely(related_command->SCpnt == NULL)) {			TRACE_ERROR("No SCSI command found for ITT %u\n",				    local_itt);		} else if (unlikely(rx_pack_cookie_from_pdu(related_session,							   current_connection,							   related_command,							   r2t_header,							   local_itt,offset,							   xfer_len) < 0)) {			TRACE_ERROR("Pack Cookie failed\n");		}	} else {		TRACE_ERROR("R2T for ITT %u, R2TSN %u, offset %u, DDTL %u, "			    "no command!\n", local_itt, r2t_sn, offset,			    xfer_len);	}	/* r2t exit added for Error Recovery - SAI */rx_r2t_out:	TRACE(TRACE_ENTER_LEAVE,		"Leave rx_r2t, current_connection %p, retval %d\n",		current_connection, retval);	return retval;}/* * Called only from rx_r2t(). * Populate a new cookie from an R2T PDU. Cookies are attached to the * command struct. Moved from rx_r2t to condense inline code * It extracts useful data from the R2T PDU and fills a new cookie. * Return 1 on success. * 	  0 on failure from create_r2t_cookie() */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){	struct r2t_cookie *cookie;	int over_flow_data_size, r2t_sn, delta;	TRACE(TRACE_ENTER_LEAVE, "Enter rx_pack_cookie\n");	r2t_sn = ntohl(r2t_header->r2t_sn);	cookie = create_r2t_cookie(related_session);	if (unlikely(cookie == NULL)) {		TRACE_ERROR("Cookie for ITT %u, R2TSN %u FAILED\n",			                    local_itt, r2t_sn);		return 0;	}	/* copy info from R2T into fields in the cookie */	cookie->offset = offset;	cookie->r2t_xfer_length = xfer_len;	if (likely(related_session->oper_param->DataSequenceInOrder)) {		/* DataSequenceInOrder=Yes */		/* Draft 20, Section 10.8 Ready to Transfer (R2T)		 * "DataSequenceInOrder governs the buffer offset ordering		 * in consecutive R2Ts. If DataSequenceInOrder is Yes,		 * then consecutive R2Ts MUST refer to continuous		 * non-overlapping ranges except for Recovery-R2Ts."		 */		/* Consider an out of seq R2T to be a recovery R2T - SAI */		delta = related_command->data_offset - offset;		if (unlikely(delta != 0)) {			/* Handle Recovery R2T without flagging errors - SAI */			if (likely(delta > 0)) {				/* recovery R2T, just backup command offset */				TRACE_WARNING("Recovery R2T for ITT %u, "				      "R2TSN %u, reset offset from %u "				      "to %u, still_to_send from %u to %u\n",				      local_itt, r2t_sn,				      related_command->data_offset, offset,				      related_command->still_to_send,				      related_command->still_to_send + delta);				related_command->still_to_send += delta;				related_command->data_offset = offset;			} else {				TRACE_ERROR("R2T for ITT %u, R2TSN %u, has "					    "buffer offset %u, expected %u\n",					    local_itt, r2t_sn, offset,					    related_command->data_offset);				/* put back this unneeded cookie structure */				uncreate_r2t_cookie(cookie, related_session);				return -1;			}		}	}#ifdef ISCSI_CHECK_PDU_FORMAT	/* Check that R2T not asking to xfer more than MaxBurstLength */	if (unlikely(xfer_len > related_session->oper_param->MaxBurstLength)) {		TRACE_ERROR ("R2T for ITT %u, R2TSN %u, has DDTL of %u bytes, "			     "exceeding allowed %s %u\n", local_itt, r2t_sn,			     xfer_len, "MaxBurstLength",			     related_session->oper_param->MaxBurstLength);		/* for now, just ignore this error -- we can		 * handle data beyond MaxBurstLength without problem		 */	}#endif	/* Check if this R2T would overflow the SCSI Mid-level buffers */	over_flow_data_size = offset + xfer_len				- related_command->SCpnt->request_bufflen;	if (unlikely(over_flow_data_size > 0)) {		TRACE_ERROR("R2T for ITT %u, R2TSN %u, has DDTL of %u bytes "			    "that overflows SCSI buffer by %d\n",			    local_itt, r2t_sn, xfer_len, over_flow_data_size);		/* accept only the remaining amount of buffer space */		if (over_flow_data_size >= xfer_len) {			/* overflow exceeds amount to be transfered */			/* put back this unneeded cookie structure */			uncreate_r2t_cookie(cookie, related_session);			return -1;		}		cookie->r2t_xfer_length -= over_flow_data_size;	}	TRACE(TRACE_DEBUG, "recvd r2t for ITT %u, R2TSN %u, offset %u, "	      "xfer length %u\n", local_itt, r2t_sn,	      related_command->data_offset, cookie->r2t_xfer_length);	hookup_r2t_cookie(cookie, related_session, current_connection,			  related_command, r2t_header->target_xfer_tag);	if (atomic_read(&current_connection->tx_sem.count) <= 0) {		/* tell xmit thread something may be ready to send */		TRACE(TRACE_ISCSI_FULL, "rx_r2t: wake up tx thread\n");		up(&current_connection->tx_sem);	}	TRACE(TRACE_ENTER_LEAVE, "Leave rx_pack_cookie\n");	return 1;}/**************************************************************************** * 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 Asynchronous Message PDU * Parameters: current_connection which is a ptr to the connection struct *			  where the PDU header was received. * Return Value: >0 success, =0 failure. ****************************************************************************/static intrx_async_msg(struct connection *current_connection, __u32 size, char *buffer){	struct iscsi_targ_async_msg *am_header;	struct session *related_session;	struct connection *conn;	__u32 lun;	int retval = 0;		/* assume this fails */	__u16 param1, param2, param3;	TRACE(TRACE_ENTER_LEAVE, "Enter rx_async_msg, current_connection %p\n",	      current_connection);	am_header = (struct iscsi_targ_async_msg *) current_connection->rx_buf;	if (unlikely(TRACE_TEST(TRACE_DEBUG))) {		debug_print_ip(current_connection, "Async Msg");	}	related_session = current_connection->my_session;#ifdef ISCSI_CHECK_PDU_FORMAT	/* Check if reserved fields are zero or not */	if (unlikely(!(((am_header->flags & ~F_BIT) == 0)		&& (am_header->rsvd2 == 0)		&& (am_header->rsvd3 == 0)		&& (am_header->rsvd5 == 0)))) {		reserved_not_0("Async Msg");	}	/* Draft 20, section 10.9.2 AsyncVCode	 * "AsyncVcode is a vendor specific detail code that is only	 * valid if the AsyncEvent field indicates a vendor specific	 * event.  Otherwise, it is reserved."	 */	if (am_header->async_vcode != 0 && am_header->async_event != 255) {		TRACE_ERROR		    ("AsyncVCode 0x%02x should be 0 when AsyncEvent is "		     "0x%02x\n",		     am_header->async_vcode, am_header->async_event);	}	/* Draft 20, section 10.9.3 LUN "The LUN field MUST be valid	 * if AsyncEvent is 0.  Otherwise, this field is reserved."	 */	if (am_header->lun != 0 && am_header->async_event != 0) {		TRACE_ERROR		    ("LUN 0x%016llx should be 0 when AsyncEvent is 0x%02x\n",		     am_header->lun, am_header->async_event);	}#endif	param1 = be16_to_cpu(am_header->parameter1);	param2 = be16_to_cpu(am_header->parameter2);	param3 = be16_to_cpu(am_header->parameter3);	switch (am_header->async_event) {	case 0:		/* SCSI Asynchronous Event */		/* check for valid LUN, per section 9.9.3 quoted above */		lun = unpack_lun((__u8 *) & am_header->lun);		if (!(related_session->lun_bits & (1 << lun))) {			TRACE_ERROR("Invalid SCSI Asynch Event LUN %u\n", lun);		}		TRACE_ERROR("Unimplemented SCSI Asynchronous Event\n");		break;	case 1:		/* target requests Logout */#ifdef ISCSI_CHECK_PDU_FORMAT		if (param1 != 0 || param2 != 0) {			TRACE_ERROR			("Parameter1 0x%04x and Parameter2 0x%04x both should "			"be 0 when AsyncEvent is 0x%02x\n",			param1, param2, am_header->async_event);		}#endif		if (current_connection->connection_flags			& SEND_NO_REPLY_TO_ASYNC_LOGOUT) {			TRACE(TRACE_ISCSI, "Not replying to Async Logout "						"request from target\n");			retval = 1;	/* success */		} else if (!drive_logout(related_session, current_connection,				 	 LOGOUT_CLOSE_SESSION)) {			TRACE_ERROR			("Unable to send Logout PDU requested by target\n");		} else	{			retval = 1;	/* success */		}		break;	case 2:		/* target dropping a specified connection */		/* NOTE we cannot just kill the connection,		 * since that might require this thread to kill		 * itself and then wait for itself to die,		 * which will not work.		 */		/* check that this CID actually matches an existing		 * connection id		 */		for (conn = related_session->connection_head;					conn != NULL; conn = conn->next) {			if (conn->connection_id == param1) {				break;			}		}		if (conn == NULL) {			TRACE_ERROR			("Target dropping connection with nonexistant CID %u\n",			param1);		} else {			TRACE(TRACE_ISCSI,			"Target dropping connection with CID %u\n", param1);		}		retval = 1;	/* success */		break;	case 3:		/* target dropping all connections in a session */		/* NOTE we cannot just kill the session, since		 * that might require this thread to kill itself		 * and then wait for itself to die, which will not work.		 */#ifdef ISCSI_CHECK_PDU_FORMAT		if (param1 != 0) {			TRACE_ERROR("Parameter1 0x%04x should be 0 "				"when AsyncEvent is 0x%02x\n",				param1, am_header->async_event);		}#endif		TRACE(TRACE_ISCSI,		      "Target dropping all connections in session\n");		retval = 1;	/* success */		break;	case 4:		/* target requests Text negotiation */		if (unlikely(drive_text_negotiate(current_connection,						related_session, 0, 0))) {			TRACE_ERROR			("Unable to send Text PDU requested by target\n");		} else {			retval = 1;	/* success */		}		break;	case 255:		/* vendor specific iSCSI Event */		TRACE(TRACE_ISCSI,			"Ignoring vendor specific iSCSI Event, "			"AsyncVcode 0x%02x\n", am_header->async_vcode);		retval = 1;	/* success */		break;	default:		TRACE_ERROR("Illegal AsyncEvent 0x%02x\n",			am_header->async_event);		retval = 1;	/* success */		break;	}			/* switch */	TRACE(TRACE_ENTER_LEAVE, "Leave rx_async_msg, retval %d\n", retval);	return retval;}/**************************************************************************** * 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 task mgt response header, sets up the * task_mgt_response field in the command struct and wakes up the * initiator_abort function (called by SCSI Midlevel) waiting on the * task_mgt_sem semaphore. * Parameters: current_connection which is a ptr to the connection struct *			  where the Task Mgt. Header was received. * Return Value: >=0, on success (always) ****************************************************************************/static intrx_task_mgt_rsp(struct connection *current_connection,		__u32 local_itt, struct command *related_command){	struct session *current_session;	struct iscsi_targ_task_mgt_response *header;	struct command *cmd;	TRACE(TRACE_ENTER_LEAVE, "Enter rx_task_mgt_rsp, current_connection"	      " %p\n", current_connection);	header = (struct iscsi_targ_task_mgt_response *)						current_connection->rx_buf;	TRACE(TRACE_DEBUG, "Got StatSN %u\n", ntohl(header->stat_sn));	/* Store the session pointer for future use - SAI */	current_session = current_connection->my_session;#ifdef ISCSI_CHECK_PDU_FORMAT	/* Check if reserved fields are zero or not */	if (unlikely(!(((header->flags & ~F_BIT) == 0)	      && (header->rsvd1 == 0)	      && (header->rsvd2 == 0)	      && (header->rsvd4 == 0)	      && (header->rsvd5 == 0)))) {		reserved_not_0("TM Response");

⌨️ 快捷键说明

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