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

📄 iscsi_initiator.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* extract ip address and port into strings for printing */		if (cnv_inet_to_string(conn->local_ip_address, local_ip_string,							local_port_string) > 0)	    		TRACE(TRACE_DEBUG,"iscsi local address %s:%s\n",					local_ip_string, local_port_string);	}#ifdef ISCSI_STATS	add_iscsi_proc_entry((void*)conn, CONNECTION);#endif	/*      Allocate buffer into which rx_thread will read	 *	PDU headers from target.  For now, we ignore AHS,	 *	so space is needed only for BHS and digest.	 */	conn->rx_buf = (__u8 *)my_kmalloc(ISCSI_HDR_LEN + CRC_LEN, "rx_buf");	if (unlikely(conn->rx_buf == NULL)) {		/* no memory for rx_buf */		retval = -ENOMEM;		goto out2;	}	/* we are connected to a target */	conn->connection_state = CONNECTION_CONNECTED;	/* chap and srp support - CHONG */	new_authparam.auth_flags = targ_data->auth_parameter.auth_flags;	new_authparam.chap_local_ctx		= CHAP_CloneContext(targ_data->auth_parameter.chap_local_ctx);	new_authparam.chap_peer_ctx		= CHAP_CloneContext(targ_data->auth_parameter.chap_peer_ctx);	new_authparam.srp_ctx		= SRP_CloneContext(targ_data->auth_parameter.srp_ctx);	/* now go do the login phase for this new connection */	retval = iscsi_initiator_login(conn, when_called, p_param_tbl,			new_authparam, targ_data, redirect_ip_address,			redirect_ip_length);	if (unlikely(retval != 0)) {		goto out3;	}	/* Create connection's rx_thread only if get into Full Feature Phase */	kernel_thread((int (*)(void *)) iscsi_initiator_rx_thread,		      (void *) conn, 0);	/* wait for the rx thread to set itself up */	down_interruptible(&conn->rx_done_sem);	if (conn->rx_thread == NULL) {		/* the rx thread has already shut itself down */		retval = -ECONNRESET;		goto out;	}	/* connection is up and running */	conn->connection_state = CONNECTION_FULL_FEATURE_PHASE;	/* start up the tx thread for this new connection */	kernel_thread((int (*)(void *)) iscsi_initiator_tx_thread,		      (void *) conn, 0);	/* wait for the tx thread to set itself up */	down_interruptible(&conn->tx_done_sem);	if (conn->rx_thread == NULL || conn->tx_thread == NULL) {		/* the rx and/or tx thread have already shut themselves down */		retval = -ECONNRESET;	}out:	CHAP_FinalizeContext(new_authparam.chap_peer_ctx);	CHAP_FinalizeContext(new_authparam.chap_local_ctx);	SRP_FinalizeContext(new_authparam.srp_ctx);out0:	TRACE(TRACE_ENTER_LEAVE, "Leave init_connection, retval %d\n", retval);	return retval;out3:	conn->connection_state = CONNECTION_NOT_PRESENT;	my_kfree((void **)&conn->rx_buf, "rx_buf");out2:	printk("%s Disconnected from %s:%s\n", current->comm, ip_string,		port_string);#ifdef ISCSI_STATS	remove_iscsi_proc_entry((void *)conn, CONNECTION);#endifout1:	sock_release(conn->sock);	conn->sock = NULL;	goto out;}/**************************************************************************** * when called, NO LOCKS SHOULD BE LOCKED! * Called only by create_session() to * 1.	initialize a new session structure * 2.	create a new first connection for the session * 3.	connect to the target * 4.	conduct the complete login phase with the target * * Return value: =1 on redirection *		 =0 on all other successes, *		 <0 on failure ****************************************************************************/static intinit_session(struct session *sess,	     struct connection *conn,	     __u32 lun,	     struct iscsi_targetdata *targ_data,	     struct sockaddr **redirect_ip_address,	     int *redirect_ip_length){	int retval = 0;	TRACE(TRACE_ENTER_LEAVE, "Enter init_session, sess %p\n", sess);	/* if not already allocated, allocate now - new 18_04 SAI */	if (!sess->oper_param) {		/*      finish allocating remaining structs		 *	new struct session points to		 */		sess->oper_param = (struct session_operational_parameters *)		    my_kmalloc(sizeof(struct session_operational_parameters),			       "session oper_param");		if (unlikely(sess->oper_param == NULL)) {			retval = -ENOMEM;			goto out;		}	}	TRACE(TRACE_ISCSI, "Create session for target %u lun %u CID %u\n",	      sess->scsi_target_id, lun, conn->connection_id);#ifdef ISCSI_STATS	add_iscsi_proc_entry((void*)sess, SESSION);#endif	/* Connect to the target and go through the complete login phase */	/* chap and srp support - CHONG */	retval = init_connection(conn, LEADING_ONLY | INITIAL_ONLY | ALL,				 *sess->session_params,				 targ_data,				 redirect_ip_address, redirect_ip_length);	if (unlikely(retval != 0))		goto out2;	sess->session_state = SESSION_LOGGED_IN;	/* successfully created a new connection for a new session	 * Set up the session-wide negotiated operational parameters for this	 * new session	 */	set_session_parameters(sess->oper_param, *sess->session_params);	TRACE(TRACE_DEBUG, "ErrorRecoveryLevel %u\n",	      sess->oper_param->ErrorRecoveryLevel);	/* force use of snack when error recovery is in effect - RDR	 *      Draft 20, Section 10.16 SNACK Request	 *      "If the implementation supports ErrorRecoveryLevel greater than	 *      zero, it MUST support all SNACK types."	 */	if (sess->oper_param->ErrorRecoveryLevel > 0) {		sess->init_snack_flag		    |= (DATA_SNACK_ENABLE | STATUS_SNACK_ENABLE);	}out:	TRACE(TRACE_ENTER_LEAVE, "Leave init_session, retval %d\n", retval);	return retval;out2:#ifdef ISCSI_STATS	remove_iscsi_proc_entry((void*)sess, SESSION);#endif	my_kfree((void **)&sess->oper_param, "session oper_param");	goto out;}/* * when called, NO LOCKS SHOULD BE LOCKED! * free up the memory allocated to a session struct, but not any connection * structs it might point to, which must already have been freed up. * Except for those connection structs, undoes the allocations in * build_session_skeleton() and those that might come later, * in the reverse order */static voidunbuild_session_skeleton( struct session *old_session ){	struct command *command;	struct r2t_cookie *cookie;	struct list_head *lptr, *next;	/* done with unused r2t cookie structures */	list_for_each_safe(lptr, next, &old_session->free_r2t_cookies) {		list_del(lptr);		cookie = list_entry(lptr, struct r2t_cookie, link);		my_kfree((void **)&cookie, "r2t cookie");	}	/* done with unused command structures */	list_for_each_safe(lptr, next, &old_session->free_commands) {		list_del(lptr);		command = list_entry(lptr, struct command, link);		my_kfree((void **)&command, "command");	}#ifdef ISCSI_STATS	my_kfree((void **)&old_session->sess_stats, "session_stats");#endif	if (old_session->session_params) {		/* done with the session's parameter table */		param_tbl_uncpy(*old_session->session_params);		my_kfree((void **)&old_session->session_params,			 "session param_tbl");	}	/* done with the session structure itself */	my_kfree((void **)&old_session, "session");}/* * when called, NO LOCKS SHOULD BE LOCKED! * create and initialize a session struct and its first connection struct */static struct session *build_session_skeleton(__u32 target, struct sockaddr *ip_address,			int ip_length, __u32 lun, __u32 cid){	struct session *new_session;	struct connection *conn;	struct iscsi_targetdata *targ_data;	new_session	    = (struct session *)my_kmalloc(sizeof(struct session), "session");	if (unlikely(new_session == NULL)) {		goto out1;	}	/* reset all fields in new struct session to 0 */	memset(new_session, 0, sizeof(struct session));	/* initialize most of the new struct session fields here */	new_session->sess_lock = UNH_LOCK_UNLOCKED;	INIT_LIST_HEAD(&new_session->free_commands);	INIT_LIST_HEAD(&new_session->free_r2t_cookies);	new_session->scsi_target_id = target;	new_session->n_luns_in_session = 1;	new_session->lun_bits = 1 << lun;	new_session->session_state = SESSION_NOT_PRESENT;	new_session->cur_task_tag = 88888;	/* something unique */	new_session->cur_cmd_sn = 22222;	/* something unique */	new_session->exp_cmd_sn = new_session->cur_cmd_sn + 1;	new_session->max_cmd_sn = new_session->exp_cmd_sn;	init_timer(&new_session->connrec_timer);	targ_data = &global_hostdata->target_data[target];	/* use the configured values to initialize following fields */	new_session->session_flags = targ_data->init_sess_flags;	new_session->init_conn_flags = targ_data->init_conn_flags;	new_session->nop_period = targ_data->nop_period;	TRACE(TRACE_TIMERS, "new session nop_period %u\n",	      new_session->nop_period);	/* Added data and status snack support - SAI */	new_session->init_snack_flag = targ_data->init_snack_flag;	/* Added the retransmit wait period - SAI */	new_session->retran_period = targ_data->retran_period;	/* Store the connection scheduling scheme - SAI */	new_session->sched_scheme = targ_data->sched_scheme;	/* allocate space for configured parameters */	new_session->session_params		= my_kmalloc(MAX_CONFIG_PARAMS * sizeof(struct parameter_type),			     "session param_tbl");	if (unlikely(new_session->session_params == NULL)) {		goto out_err;	}	/* init session parameters with copy of configured parameter table */	param_tbl_cpy(*new_session->session_params, targ_data->param_tbl);#ifdef ISCSI_STATS	/* get stats structure */	new_session->sess_stats =	    (struct iscsi_session_stats*)my_kmalloc(sizeof(struct iscsi_session_stats),						      "session_stats");	if (unlikely(new_session->sess_stats == NULL)) {	    goto out_err;	}	/* reset all the stats field */	memset(new_session->sess_stats, 0, sizeof(struct iscsi_session_stats));#endif		/* create the first connection on this session */	conn = (struct connection *)my_kmalloc(sizeof(struct connection),						"connection");	if (unlikely(conn == NULL)) {		/* no memory for new connection structure */		goto out_err;	}	/* reset all fields in new struct connection */	memset(conn, 0, sizeof(struct connection));	conn->connection_id = cid;	/* target's default MaxRecvDataSegmentLength */	conn->max_send_length = 8192;	/* initiator's MaxRecvDataSegmentLength */	conn->max_recv_length = 8192;	conn->nop_counter = 1;	conn->my_session = new_session;	conn->connection_flags = new_session->init_conn_flags;	conn->connection_state = CONNECTION_NOT_PRESENT;	init_MUTEX_LOCKED(&conn->rx_done_sem);	init_MUTEX_LOCKED(&conn->tx_sem);	init_MUTEX_LOCKED(&conn->tx_done_sem);	init_MUTEX_LOCKED(&conn->task_mgt_sem);	init_timer(&conn->tx_timer);	INIT_LIST_HEAD(&conn->pending_commands);	INIT_LIST_HEAD(&conn->r2t_list);	conn->ip_address = ip_address;	conn->ip_length = ip_length;	/* point fields in new session at new connection */	new_session->nconnections = 1;	new_session->connection_head = conn;	new_session->rr_conn_head = conn;	/* pre-allocate maximum number command structures session may use	 * (one extra in case of task-management and/or nopout commands)	 */	if (unlikely(preallocate_commands(new_session) == 0)) {		goto out_err;	}out:	return new_session;out_err:	unbuild_session_skeleton(new_session);out1:	TRACE(TRACE_NET, "Free ip_address %p\n", ip_address);	my_kfree((void **)&ip_address, "ip_address");	goto out;}static intadd_session_to_hostdata(struct connection *new_connection, __u32 lun,			struct session *new_session, struct Scsi_Host *host);/**************************************************************************** * when called, NO LOCKS SHOULD BE LOCKED! * executed by rx thread or tx thread or init_recovery thread or command process * Creates and initializes a new session and its first connection struct by * calling corresponding functions. It then tries to connect to the target. * Called from iscsi_initiator_proc_info() when a line such as * 	"iscsi_initiator ip 1234abcd port 4000 target 1 lun 2 cid 3" * is written to /proc/scsi/iscsi_initiator/0 * also called from create_rec_conn() to create a recovery connection * Return value: * 	=1 on success -- new session added, logged in, now in FFP * 	=2 on success -- new lun added to existing session * 	=0 on success -- new connection added, logged in, now in FFP *			 or new discovery session added, now in FFP * 	<0 on failure -- value is errno negated ****************************************************************************/intcreate_session(__u32 target, struct sockaddr *ip_address, int ip_length,		__u32 lun, __u32 cid, struct Scsi_Host *host){	unsigned long lock_flags;	int i, retval, redirect_count = 0;	struct sockaddr *redirect_ip_address;	int redirect_ip_length;	struct session *new_session;	struct connection *conn;	struct iscsi_hostdata *hostdata	    = (struct iscsi_hostdata *) host->hostdata;	if (unlikely(TRACE_TEST(TRACE_ENTER_LEAVE))) {		char ip_string[INET6_ADDRSTRLEN+2];		char port_string[8];		if (cnv_inet_to_string(ip_address,ip_string,port_string) < 0) {			/* should never happen */			TRACE_ERROR("bad ip_address\n");			TRACE(TRACE_NET, "Free ip_address %p\n", ip_address);			my_kfree((void **)&ip_address, "ip_address");			/* software caused connection abort */			return -ECONNABORTED;		}		TRACE(TRACE_ENTER_LEAVE,				"Enter create_session to %s:%s, "				"target %u, lun %u, cid %u\n", ip_string,				port_string, target, lun, cid);	}retry:	/* here to try again on a redirection */

⌨️ 快捷键说明

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