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

📄 iscsi_target.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		list_for_each_safe(list_ptr, list_temp, &devdata->session_list) {			session = list_entry(list_ptr, struct iscsi_session, sess_link);			iscsi_release_session(session);		}		list_for_each_safe(list_ptr, list_temp, &devdata->bad_session_list) {			session = list_entry(list_ptr, struct iscsi_session, sess_link);			TRACE(TRACE_DEBUG, "iscsi%d: release bad session %p, tsih %u\n",			  	(int) devdata->device->id, session, session->tsih);			iscsi_release_session(session);		}		up(&devdata->session_sem);	}		bring_down_portals();out:	TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_release, err %d\n", err);	return err;}/* print socket connect/disconnect message */voidreport_peer_up_down(struct sockaddr *ip_address, char *message){	char ip_string[INET6_ADDRSTRLEN+2], port_string[8];	if (cnv_inet_to_string(ip_address, ip_string, port_string) > 0) {		printk("%s %s %s:%s\n", current->comm, message,													ip_string, port_string);	}}/* * generate the next TTT in a session * must be called with session->cmnd_sem lock held */static inline __u32 __attribute__ ((no_instrument_function))generate_next_ttt(struct iscsi_session* session){	__u32 retval;	retval = session->cmnd_id++;	if (session->cmnd_id == 0) {		/* just assigned -1 to retval, which is reserved		 * so do it again, since 0 is not reserved		 */		retval = session->cmnd_id++;	}	return retval;}/* * allocates all the structures necessary for a new connection and a * new session.  If later we find out that this connection belongs to * an existing session, the session structure alloced here will be * freed.  Its just easier to do everything here in one place, and it * makes it easier to recover from errors if everything is all set up * (i.e., there are no partial structures) * returns NULL if anything fails, in which case everything is freed *		   pointer to new iscsi_conn, which points to new iscsi_sess, if all ok */static struct iscsi_conn *build_conn_sess(struct socket *sock, struct portal_group *ptr){	struct iscsi_conn *conn;	struct iscsi_session *session;	int addr_len;	conn = (struct iscsi_conn *)my_kmalloc(sizeof(struct iscsi_conn),										   "iscsi_conn");	if (!conn) {		goto out1;	}	TRACE(TRACE_DEBUG, "new conn %p for sock %p\n", conn, sock);	memset(conn, 0, sizeof(struct iscsi_conn));	INIT_LIST_HEAD(&conn->conn_link);	INIT_LIST_HEAD(&conn->reject_list);	init_MUTEX(&conn->reject_sem);	conn->active = 1;	conn->conn_id = ++devdata->conn_id;	conn->conn_socket = sock;	conn->dev = devdata;	conn->max_send_length = 8192;	conn->max_recv_length = 8192;	conn->portal_group_tag = ptr->tag;	conn->connection_flags = devdata->force;	conn->nop_period = devdata->nop_period;	init_timer(&conn->nop_timer);	init_MUTEX_LOCKED(&conn->tx_sem);	init_MUTEX_LOCKED(&conn->kill_rx_sem);	init_MUTEX_LOCKED(&conn->kill_tx_sem);	init_MUTEX(&conn->text_in_progress_sem);	/* get ip addressing info about both ends of this connection */	if ((conn->ip_address = my_kmalloc(sizeof(struct sockaddr), "ip address"))								== NULL) {		goto out2;	}	addr_len = ptr->ip_length;		/* value-result parameter */	if (sock->ops->getname(sock, conn->ip_address, &addr_len, 1) < 0) {		TRACE_ERROR("%s Could not get peer name for socket %p\n", current->comm,					sock);		goto out3;	}	if ((conn->local_ip_address = my_kmalloc(sizeof(struct sockaddr),											 "local ip address")) == NULL) {		goto out3;	}	addr_len = ptr->ip_length;		/* value-result parameter */	if (sock->ops->getname(sock, conn->local_ip_address, &addr_len, 0) < 0) {		TRACE_ERROR("%s Could not get local name for socket %p\n",					current->comm, sock);		goto out4;	}	session = (struct iscsi_session *)my_kmalloc(sizeof(struct iscsi_session),												 "session");	if (!session) {			goto out4;	}	memset(session, 0, sizeof(struct iscsi_session));	INIT_LIST_HEAD(&session->sess_link);	INIT_LIST_HEAD(&session->conn_list);	list_add_tail(&conn->conn_link, &session->conn_list);	conn->session = session;	session->nconn = 1;	session->devdata = devdata;	session->portal_group_tag = ptr->tag;	session->version_max = ISCSI_MAX_VERSION;	session->version_min = ISCSI_MIN_VERSION;	if ((session->r2t_timer = (struct timer_list *)				my_kmalloc(sizeof(struct timer_list), "r2t timer")) == NULL) {				goto out5;	}	init_timer(session->r2t_timer);	TRACE(TRACE_DEBUG, "Allocated R2T timer %p for session %p\n",		  session->r2t_timer, session);	if (!(session->session_params = my_kmalloc(MAX_CONFIG_PARAMS *											   sizeof(struct parameter_type),											   "session_params"))) {		goto out6;	}	if (!(session->oper_param = my_kmalloc(MAX_CONFIG_PARAMS *								sizeof(struct session_operational_parameters),								"oper_param"))) {		goto out7;	}	/* copy the parameters information from the global structure */	param_tbl_cpy(*session->session_params, *devdata->param_tbl);	session->r2t_period = devdata->r2t_period;	/* Store SNACK flags as part of Session - SAI */	session->targ_snack_flg = devdata->targ_snack_flg;	init_MUTEX(&session->cmnd_sem);	init_MUTEX_LOCKED(&session->retran_sem);	init_MUTEX_LOCKED(&session->thr_kill_sem);	/* all ok */	goto out;out7:	my_kfree((void**)&session->session_params, "session_params");out6:	TRACE(TRACE_DEBUG, "Releasing R2T timer %p for session %p\n",		  session->r2t_timer, session);	my_kfree((void**)&session->r2t_timer, "r2t timer");out5:	my_kfree((void**)&session, "session");out4:	my_kfree((void**)&conn->local_ip_address, "local ip address");	out3:	my_kfree((void**)&conn->ip_address, "ip address");out2:	my_kfree((void**)&conn, "iscsi_conn");	out1:	sock_release(sock);out:	return conn;}/* * iscsi_server_thread: This thread is responsible for accepting * connections */intiscsi_server_thread(void *param){	struct iscsi_conn *new_conn;	struct socket *newsock, *sock;	struct portal_group *ptr = param;	long i;	i = ptr - iscsi_portal_groups;		lock_kernel();/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else	daemonize();	snprintf(current->comm, sizeof(current->comm),#endif			 "iscsi_thr_%ld", i);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)	/*	 * Arne Redlich, agr1@users.sourceforge.net:	 * This prevents the server thread from becoming a zombie after it exits.	 */	reparent_to_init();#endif	siginitsetinv(&current->blocked, ISCSI_SHUTDOWN_SIGBITS);	/* mark that this server thread is alive */	devdata->server_thr[i] = current;	unlock_kernel();	printk("%s Starting pid %d\n", current->comm, current->pid);	sock = devdata->server_socket[i];	printk("%s Listening on %s:%s\n", current->comm,											ptr->ip_string,											ptr->port_string);	/* notify our parent that this thread is up */	up(&devdata->server_sem);	/* loop forever accepting new connections from initiators */	for ( ; ; ) {	/* fix for 2.6.10 contributed by Charles Coffing, ccoffing@novell.com */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 9)		newsock = sock_alloc();		if (!newsock)#else		int ret;		ret = sock_create_kern(sock->sk->sk_family, sock->type,							   sock->sk->sk_protocol, &newsock);		if (ret)#endif		{			TRACE_ERROR("%s Could not allocate socket for accept\n",						current->comm);			goto iscsi_server_thread_out;		}		newsock->type = sock->type;		newsock->ops = sock->ops;		TRACE(TRACE_NET, "before accept: sock %p newsock %p\n", sock, newsock);		if (sock->ops->accept(sock, newsock, 0) < 0) {			goto out1;		}		TRACE(TRACE_NET, "after accept: sock %p newsock %p\n", sock, newsock);		/* turn off the Nagle Algorithm on this socket */		tcp_nagle_off(newsock);		/* clear bad sessions and connections here */		clean_bad_stuff();		/* allocate and fill in connection details */		if ((new_conn = build_conn_sess(newsock, ptr)) == NULL)			goto iscsi_server_thread_out;		TRACE(TRACE_ISCSI, "Connect socket %p on conn %p, cid %d, session %p\n",			  newsock, new_conn, new_conn->conn_id, new_conn->session);		/* 		 * NOTE THAT WE CANNOT DO MUCH OF ANYTHING WITH THIS		 * CONNECTION AS WE DO NOT KNOW WHAT SESSION IT BELONGS		 * TO. THIS WILL HAVE TO BE A PART OF THE RX_THREAD		 */		/* start the tx thread */		if (kernel_thread(iscsi_tx_thread, (void *)new_conn, 0) < 0) {			TRACE_ERROR("%s unable to create tx_thread\n", current->comm);			goto out1;		}		/* start the rx thread */		if (kernel_thread(iscsi_rx_thread, (void *)new_conn, 0) < 0) {			TRACE_ERROR("%s unable to create rx_thread\n", current->comm);			if (new_conn->tx_thread) {				/*  Mike Christie mikenc@us.ibm.com */				send_sig(ISCSI_SHUTDOWN_SIGNAL, new_conn->tx_thread, 1);			}			goto out1;		}	}out1:	sock_release(newsock);iscsi_server_thread_out:	/* mark that this server thread is no longer alive */	devdata->server_thr[i] = NULL;	printk("%s closed %s:%s\n", current->comm,							ptr->ip_string,							ptr->port_string);	/* exit this thread after notifying whoever might be waiting */	up(&devdata->server_sem);	printk("%s Exiting pid %d\n", current->comm, current->pid);	return 0;}/* * for each session on the list, * release inactive connections and the session itself if no conns remain. * devdata->session_sem MUST be locked before this routine is called. */static void __attribute__ ((no_instrument_function))clean_session_list(struct list_head *list){	struct iscsi_session *session;	struct iscsi_conn *conn;	struct list_head *list_ptr1, *list_temp1;	struct list_head *list_ptr2, *list_temp2;	list_for_each_safe(list_ptr1, list_temp1, list) {		session = list_entry(list_ptr1, struct iscsi_session, sess_link);		list_for_each_safe(list_ptr2, list_temp2, &session->conn_list) {			conn = list_entry(list_ptr2, struct iscsi_conn, conn_link);			if (conn->active == 0) {				if (iscsi_release_connection(conn) < 0) {					TRACE_ERROR("%s Error releasing connection\n",								current->comm);				}			}		}		if (list_empty(&session->conn_list)) {			iscsi_release_session(session);		}	}}static void __attribute__ ((no_instrument_function))clean_bad_stuff(void){	/* destructive access to session lists */	if (!down_interruptible(&devdata->session_sem)) {		clean_session_list(&devdata->bad_session_list);		clean_session_list(&devdata->session_list);		up(&devdata->session_sem);	}}/* * iscsi_release_session: This function is responsible for closing out * a session and removing it from whatever list it is on. * host->session_sem MUST be locked before this routine is called. * INPUT: session to be released * OUTPUT: 0 if success, < 0 if there is trouble */intiscsi_release_session(struct iscsi_session *session){	struct iscsi_cmnd *cmnd;	struct iscsi_conn *conn;	struct list_head *list_ptr, *list_temp;	if (!session) {		TRACE_ERROR("%s Cannot release a NULL session\n", current->comm);		return -1;	}	if (TRACE_TEST(TRACE_ISCSI)) {		print_isid_tsih_message(session, "Release session with ");	}	TRACE(TRACE_DEBUG, "Releasing R2T timer %p for session %p\n",		  session->r2t_timer, session);	/* Delete r2t timer - SAI */	if (session->r2t_timer) {		TRACE(TRACE_DEBUG, "Deleting r2t timer %p\n", session->r2t_timer);		del_timer_sync(session->r2t_timer);		TRACE(TRACE_DEBUG, "Deleted r2t timer\n");		my_kfree((void**)&session->r2t_timer, "r2t timer");	}	/* free commands */	while ((cmnd = session->cmnd_list)) {		session->cmnd_list = cmnd->next;		if (cmnd->cmnd != NULL) {			if (scsi_release(cmnd->cmnd) < 0) {				TRACE_ERROR("%s Trouble releasing command, opcode 0x%02x, "							"ITT %u, state 0x%x\n", current->comm,							cmnd->opcode_byte, cmnd->init_task_tag,							cmnd->state);			}		}		/* free data_list if any, cdeng */		free_data_list(cmnd);		my_kfree((void**)&cmnd->ping_data, "data_buf");		my_kfree((void**)&cmnd, "iscsi_cmnd");	}	/* free connections */	list_for_each_safe(list_ptr, list_temp, &session->conn_list) {		conn = list_entry(list_ptr, struct iscsi_conn, conn_link);		TRACE(TRACE_ISCSI, "iscsi%d: releasing connection %d\n", (int)			  session->devdata->device->id, conn->conn_id);		if (iscsi_release_connection(conn) < 0) {			TRACE_ERROR("%s Trouble releasing connection\n", current->comm);		}	}	/* dequeue session if it is linked into some list */	if (!list_empty(&session->sess_link)) {		list_del(&session->sess_link);		/* error recovery ver new 18_04 - SAI */		if (session->retran_thread) {			/*  Mike Christie mikenc@us.ibm.com */			send_sig(ISCSI_SHUTDOWN_SIGNAL, session->retran_thread, 1);			down_interruptible(&session->thr_kill_sem);		}	}	/* free session structures */	my_kfree((void**)&session->session_params, "session_params");	my_kfree((void**)&session->oper_param, "oper_param");	my_kfree((void**)&session, "session");	return 0;}/* * called by both rx and tx threads, but only after the rx thread has been * started on a connection (so the connected message has been given). * if socket for this conn has not already been released, do it now and * print a message that says we disconnected. * Also NULL out the conn's socket so we don't try to do this again later. */static voidiscsi_release_socket(struct iscsi_conn *conn){

⌨️ 快捷键说明

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