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

📄 iscsi_initiator.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* turn on (almost) all tracing while processing an abort */	TRACE_GET(save_trace);	TRACE_SET(TRACE_ALL		    & ~(TRACE_ISCSI_FULL|TRACE_ENTER_LEAVE|TRACE_MY_MEMORY));	TRACE(TRACE_ENTER_LEAVE, "Enter iscsi_initiator_abort\n");/* RDR */#ifndef K26	/* unlock the lock obtained by the scsi midlevel before calling us */	spin_unlock(&io_request_lock);#endif	/* get exclusive access to the iscsi structures */	if (!find_aborted_command(Cmnd, &related_session, &related_connection,				  &related_command, 1, &lock_flags)) {		goto out;	}	/* Successfully found the matching command to be aborted.	 * Corresponding session, connection and command are valid.	 * Session lock is held.  Mark this command as being aborted.	 */	related_command->cmd_state |= CMD_STATE_ABORTING;	if (related_command->cmd_state & CMD_STATE_TXSTARTED) {		/* this command was previously sent to target, so we now have		   to send a task management function command to the target */		tm_send_and_wait(Cmnd, related_session, related_connection,				&related_command, &lock_flags);		if (related_command == NULL )			goto out_session_lock_held;	}	retval = SUCCESS;	/* Free command struct for the SCSI command that had to be aborted */	/* error recovery - SAI */	Cmnd->result = DID_ABORT << 16;	related_command->cmd_state |= CMD_STATE_RXDONE | CMD_STATE_TXDONE;	free_pending_command(related_command, related_connection);	TRACE(TRACE_DEBUG, "Freed aborted command, ITT %u\n",			related_command->init_task_tag);out_session_lock_held:	UNH_UNLOCK(&related_session->sess_lock, lock_flags);out:/* RDR */#ifndef K26	/* get back lock so caller in scsi midlevel can release it! */	spin_lock(&io_request_lock);#endif	TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_initiator_abort, 0x%04x\n",	      retval);	/* restore tracing to what it was when we came in here */	TRACE_SET(save_trace);	return retval;}/******************************************************************************	This function is called by the SCSI Mid-level.*	(via the eh_device_reset_handler field in the*	Scsi_Host_Template driver_template)*	Still need to implement this function!!*****************************************************************************/static intiscsi_initiator_reset(struct scsi_cmnd * Cmnd){	TRACE(TRACE_ENTER_LEAVE, "Enter iscsi_initiator_reset\n");	TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_initiator_reset, 0x%04x\n",	      SUCCESS);	return SUCCESS;}static intscan_redirect_address(char *string, struct sockaddr **ip_address,			int *ip_length){	int retval;	char *ptr;	if (*string == '[') {		/* start of a bracketed IPv6 address */		if ((ptr = strchr(string, ']')) == NULL) {			TRACE_ERROR("Illegal bracketed IPv6 address %s\n",									string);	    		retval = -ECONNABORTED;		} else {			/* see if a port was supplied or not */			if (*(ptr+1) == ':') {				ptr++;			} else {				ptr = ISCSI_WKP_STRING;			}			if ((retval = cnv_string_to_inet(string+1, ptr,					ip_address, ip_length)) != AF_INET6) {				if (retval >= 0) {					TRACE_ERROR("Illegal bracketed IPv6 "							"address %s\n", string);		    			retval = -ECONNABORTED;				}			}		}	} else {		/* must be start of an IPv4 address */		if ((ptr = strchr(string, ':'))) {			ptr++;		} else {			ptr = ISCSI_WKP_STRING;		}		if ((retval = cnv_string_to_inet(string, ptr, ip_address,						ip_length)) != AF_INET) {			if (retval >= 0) {				TRACE_ERROR("Illegal IPv4 address %s\n",string);				retval = -ECONNABORTED;			}		}	}	return retval;}/* set up the 6-byte isid from values configured for this target * configured values limited to 2 bits for type, 24 bits for number & qualifier * * RFC 3720 Section 10.12.5 ISID * T = 00b *	A&B - 22-bit OUI *	C&D - 24-bit qualifier * T = 01b *	A - 6-bit Reserved *	B&C - 24-bit IANA Enterprise Number *	D - 16-bit Qualifier * T = 10b *	A - 6-bit Reserved *	B&C - 24-bit Random number *	D - 16-bit Qualifier * T = 11b *	A, B, C, D - Reserved */static void __attribute__ ((no_instrument_function))setup_isid(struct iscsi_targetdata *targ_data, __u32 *isid){	__u32 temp;	__u16 qual, *ptr16 = (__u16 *)&isid[1];	temp = targ_data->isid_type << 30;	qual =	targ_data->isid_qualifier;	switch (targ_data->isid_type) {	case 0:	/* OUI Format */		temp |= ((targ_data->isid_number & MASK_22_BITS)<<8)			| ((targ_data->isid_qualifier >> 16) & MASK_8_BITS);		break;	case 1:	/* EN Format */	case 2:	/* Random Format */		temp |= targ_data->isid_number;		break;	case 3:	/* Reserved Format */		qual = 0;		break;	}	/* switch */	*isid = htonl(temp);	*ptr16 = htons(qual);}/******************************************************************************	Sets the session operation parameters and changes the session*	state to LOGGED_IN, meaning the initiator is in done with login phase.*	Called only from init_connection()*	Return value:	=1 on redirection*			=0 on any other success*			<0 on failure*****************************************************************************/static intiscsi_initiator_login(struct connection *current_connection,		      __u32 when_called,		      struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS],		      struct auth_parameter_type auth_param,		      struct iscsi_targetdata *targ_data,		      struct sockaddr **redirect_ip_address,		      int *redirect_ip_length)/* chap and srp support - CHONG */{	int retval = 0, cid;	int login_task_tag;	__u32 isid[2];	struct session *current_session;	__u32 pdu_version_number = 0;	struct parameter_type *p;#ifdef ISCSI_STATS	unsigned long flags;#endif	TRACE(TRACE_ENTER_LEAVE,	      "Enter iscsi_initiator_login, current connection %p\n",	      current_connection);	current_session = current_connection->my_session;	/* set up the 6-byte isid */	setup_isid(targ_data, isid);	cid = current_connection->connection_id;	/* for offset 20 */	/* initialize task tag for the whole login process */	/* then update the session's task tag counter */	login_task_tag = current_session->cur_task_tag++;	TRACE(TRACE_DEBUG, "iscsi_initiator_login pdu_version_number %u\n",	      pdu_version_number);	/* In login phase always disable Header & Data Digests */	current_connection->connection_flags &= ~USE_HEADERDIGEST;	current_connection->connection_flags &= ~USE_DATADIGEST;	current_connection->basic_hdr_len = ISCSI_HDR_LEN;	retval = initiator_parameter_negotiate(current_connection->sock,			p_param_tbl,			auth_param,			&current_session->cur_cmd_sn, login_task_tag, isid,			&current_session->tsih,			cid,			&current_connection->connection_flags,			pdu_version_number,			when_called,			&current_connection->exp_stat_sn,			&current_connection->max_send_length,			&current_connection->max_recv_length);	if (unlikely(retval < 0)) {			TRACE(TRACE_ISCSI, "parameter negotiation failed\n");			/* software caused connection abort */			retval = -ECONNABORTED;			goto out;	} else if (likely(retval == 0)) {		/* new connection negotiation finished successfully */		if (current_connection->connection_flags & USE_HEADERDIGEST)			current_connection->basic_hdr_len += CRC_LEN;		current_connection->connection_state = CONNECTION_LOGGED_IN;#ifdef ISCSI_STATS		UNH_LOCK(&host_data_lock, flags);		global_hostdata->instance_stats.iscsi_intr_login_accept_rsp++;		UNH_UNLOCK(&host_data_lock, flags);#endif	} else {		/* have a redirection attempt */#ifdef ISCSI_STATS		UNH_LOCK(&host_data_lock, flags);		global_hostdata->instance_stats.iscsi_intr_login_redirect_rsp++;		UNH_UNLOCK(&host_data_lock, flags);#endif		p = find_parameter(TARGETADDRESS, p_param_tbl);		if (unlikely(p == NULL)) {			/* could not find TargetAddress key */			TRACE_ERROR("Cannot find %s key\n", TARGETADDRESS);			retval = -ECONNABORTED;		} else if (!IS_KEY_GOT_FROM_OTHER_SIDE(p->neg_info)) {			/* target never sent us this key */			TRACE_ERROR			    ("Target never sent TargetAddr key on Redirectn\n");			retval = -ECONNABORTED;		} else if (scan_redirect_address(p->str_value,				redirect_ip_address, redirect_ip_length) < 0) {			retval = -ECONNABORTED;		}	}out:#ifdef ISCSI_STATS	if (retval == -ECONNABORTED) {	    struct timeval tv;	    /*	     * Do do_gettimeofday() and find_parameter()	     * before holding the lock to reduce the lock hold	     * up time.	     */	    do_gettimeofday(&tv);	    p = find_parameter(TARGETNAME, p_param_tbl);	    UNH_LOCK(&host_data_lock, flags);	    global_hostdata->instance_stats.iscsi_intr_login_failure++;	    global_hostdata->instance_stats.iscsi_intr_last_failure_time=tv;	    if (p != NULL && p->str_value) {		strreplace(&(global_hostdata->instance_stats.iscsi_intr_last_tgt_failure_name),			p->str_value);	    }	    if (current_connection->ip_address) {	    	if (!global_hostdata->instance_stats.iscsi_intr_last_tgt_failure_address)	    		global_hostdata->instance_stats.iscsi_intr_last_tgt_failure_address				= my_kmalloc(sizeof(struct sockaddr), "failure address");	    	if (global_hostdata->instance_stats.iscsi_intr_last_tgt_failure_address)	    		memcpy(global_hostdata->instance_stats.iscsi_intr_last_tgt_failure_address,			current_connection->ip_address,			sizeof(struct sockaddr));	    }	    UNH_UNLOCK(&host_data_lock, flags);	}#endif	TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_initiator_login, retval %d\n",	      retval);	return retval;}/**************************************************************************** * when called, NO LOCKS SHOULD BE LOCKED! * Initializes the fields of the first connection in a new session, * connects to a remote target, logs in to it, * and creates the rx_thread for that connection * if full feature phase has been attained successfully. * Called by create_session() when adding new connection to existing session * and by init_session() when this is first connection in a new session. * Return value: =1 for redirection, *		 =0 for any other success, *		 <0 for error ****************************************************************************/static intinit_connection(struct connection *conn,		__u32 when_called,		struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS],		struct iscsi_targetdata *targ_data,		struct sockaddr **redirect_ip_address,		int *redirect_ip_length){	int retval;	struct auth_parameter_type new_authparam;	char ip_string[INET6_ADDRSTRLEN+2], port_string[8];	char local_ip_string[INET6_ADDRSTRLEN+2], local_port_string[8];	int local_addr_len;	/* extract address family into retval, ip address and port in strings */	retval = cnv_inet_to_string(conn->ip_address, ip_string, port_string);	if (unlikely(retval < 0)) {		TRACE_ERROR("%s\n", ip_string);		goto out0;	}	TRACE(TRACE_ENTER_LEAVE, "Enter init_connection, conn %p, sess %p\n",	      			conn, conn->my_session);	TRACE(TRACE_ISCSI, "Create connection %p to target %u CID %u "			"at %s:%s family %d\n", conn,	      		conn->my_session->scsi_target_id, conn->connection_id,			ip_string, port_string, retval);	/* finish allocating fields of new struct connection */#ifdef FC2	retval = sock_create(retval, SOCK_STREAM, 0, &conn->sock, 0);#else	retval = sock_create(retval, SOCK_STREAM, 0, &conn->sock);#endif	if (unlikely(retval < 0)) {		TRACE_ERROR("Can't create socket, error %d\n", -retval);		goto out0;	}	TRACE(TRACE_NET, "Created socket %p\n", conn->sock);/* Ming Zhang, mingz@ele.uri.edu */#ifndef K26	/* to keep tcp from strangling due to lack of memory, force tcp's	   calls to alloc_skb() to use atomic allocation, not GFP_KERNEL */	conn->sock->sk->allocation = GFP_ATOMIC;#endif	/* auth support- CHONG */	new_authparam.auth_flags = 0;	new_authparam.chap_local_ctx = NULL;	new_authparam.chap_peer_ctx = NULL;	new_authparam.srp_ctx = NULL;	retval = conn->sock->ops->connect(conn->sock, conn->ip_address,			     		  conn->ip_length, 0);	printk("%s to target %u cid %u at %s:%s conn %p\n",	       retval < 0 ? "***ERROR*** can't connect" : "Connected",	       conn->my_session->scsi_target_id, conn->connection_id,	       ip_string, port_string, conn);	if (unlikely(retval < 0)) {		/* turn on (almost) all tracing after this call */		if (TRACE_TEST(TRACE_DEBUG)) {			TRACE_SET(TRACE_ALL		    & ~(TRACE_ISCSI_FULL|TRACE_ENTER_LEAVE|TRACE_MY_MEMORY));		}		goto out1;	}	/* Turn off the Nagle Algorithm on this connection */	tcp_nagle_off(conn->sock);	/* 	 * Get the socket details - local IP/port	 * You should't fail here unless you have failed in	 * connect() call in which case, you won't be here.	 */	local_addr_len = conn->ip_length;	/* value-result parameter */	if (conn->local_ip_address == NULL)		conn->local_ip_address = my_kmalloc(sizeof(struct sockaddr),							"local_ip_address");	if (conn->local_ip_address != NULL		&& conn->sock->ops->getname(conn->sock, conn->local_ip_address,						&local_addr_len, 0) == 0) {

⌨️ 快捷键说明

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