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

📄 iscsi_target.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (conn->conn_socket != NULL) {		/* Release socket */		TRACE(TRACE_ISCSI, "Release socket %p on conn %p, cid %d, session %p\n",			  conn->conn_socket, conn, conn->conn_id, conn->session);		report_peer_up_down(conn->ip_address, "disconnected from");		sock_release(conn->conn_socket);		conn->conn_socket = NULL;	}}/* * iscsi_release_connection: releases all the stuff related to a conn. * Right now, it does not do anything for releasing commands specific * to a connection since commands are more specific to a session as * against a connection. It also dequeues the connection from the list */static intiscsi_release_connection(struct iscsi_conn *conn){	if (!conn) {		TRACE_ERROR("%s Cannot release NULL connection/n", current->comm);		return -1;	}	/* dequeue any unsent reject messages (do not send them) */	dequeue_reject(conn, 0);	/* Kill the rx and tx thread */	if (conn->rx_thread) {		/*  Mike Christie mikenc@us.ibm.com */		TRACE(TRACE_ISCSI, "Releasing iscsi_rx_%d\n", conn->conn_id);		send_sig(ISCSI_SHUTDOWN_SIGNAL, conn->rx_thread, 1);		down_interruptible(&conn->kill_rx_sem);	}	if (conn->tx_thread) {		TRACE(TRACE_ISCSI, "Releasing iscsi_tx_%d\n", conn->conn_id);		/*  Mike Christie mikenc@us.ibm.com */		send_sig(ISCSI_SHUTDOWN_SIGNAL, conn->tx_thread, 1);		down_interruptible(&conn->kill_tx_sem);	}	/* Release socket */	iscsi_release_socket(conn);	TRACE(TRACE_ISCSI_FULL, "Dequeue connection conn->cid %u\n", conn->conn_id);	/* Dequeue connection */	list_del(&conn->conn_link);	conn->session->nconn--;	/* Free connection */	my_kfree((void **)&conn->local_ip_address, "local ip address");	my_kfree((void **)&conn->ip_address, "ip address");	del_timer_sync(&conn->nop_timer);	my_kfree((void**)&conn, "conn");	return 0;}/* * executed only by the rx thread. * Allocates new reject item, fills it in with header of rejected pdu, * and enqueues it for tx thread on reject_list of this connection. */intenqueue_reject(struct iscsi_conn *conn, __u8 reason){	int err = 0;	struct reject_item	*new_item;	TRACE(TRACE_ENTER_LEAVE, "Enter enqueue_reject, reason %u\n", reason);	if ((new_item = (struct reject_item *)my_kmalloc(sizeof(struct reject_item),													 "reject item")) == NULL) {		err = -1;		goto out;	}	memcpy(new_item->bad_header, conn->bad_hdr, ISCSI_HDR_LEN);	new_item->reason = reason;	if (down_interruptible(&conn->reject_sem)) {		my_kfree((void **)&new_item, "reject item");		err = -1;		goto out;	}	list_add_tail(&new_item->reject_link, &conn->reject_list);	up(&conn->reject_sem);	if (atomic_read(&conn->tx_sem.count) <= 0) {		up(&conn->tx_sem);	}out:	TRACE(TRACE_ENTER_LEAVE, "Leave enqueue_reject, err %d\n", err);	return err;}/* * executed only by the tx thread. * locks connection's queue of pending rejects, then takes each item off * queue in order and uses it to generate and send a Reject pdu to initiator. */static intdequeue_reject(struct iscsi_conn *conn, int sendit){	int err = 0;	struct reject_item	*item;	struct list_head *list_ptr, *list_temp;	if (down_interruptible(&conn->reject_sem)) {		err = -1;		goto out;	}	list_for_each_safe(list_ptr, list_temp, &conn->reject_list) {		item = list_entry(list_ptr, struct reject_item, reject_link);		if (sendit)			err = iscsi_tx_rjt(conn, item->bad_header, item->reason);		list_del(list_ptr);		my_kfree((void **)&item, "reject item");		if (err)			break;	}	up(&conn->reject_sem);out:	return err;}/*  * iscsi_rx_thread: This thread is responsible for receiving iSCSI PDUs * and messages from the Initiator and then figuring out what to do with * them */intiscsi_rx_thread(void *param){	struct iscsi_conn *conn = (struct iscsi_conn *) param;	struct iovec iov;				/* for reading header and header digest */	struct targ_error_rec err_rec;	__u8 buffer[ISCSI_HDR_LEN];		/* read 48-byte PDU header in here */	__u32 digest;					/* read 4-byte header digest in here */	__u32 hdr_crc;					/* compute PDU header digest in here */	__u32 opcode;					/* extract 6-bit PDU opcode into here */	__u32 local_itt;				/* convert 4-byte PDU ITT into here */	int err;	lock_kernel();/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else	daemonize();	sprintf(current->comm,#endif			"iscsi_rx_%d", conn->conn_id);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)	/*	 * Arne Redlich, agr1@users.sourceforge.net:	 * This prevents the rx_thread from becoming a zombie after it exits.	 */	reparent_to_init();#endif	siginitsetinv(&current->blocked, ISCSI_SHUTDOWN_SIGBITS);	/* mark that this rx thread is alive */	conn->rx_thread = current;	unlock_kernel();	printk("%s Starting pid %d\n", current->comm, current->pid);	report_peer_up_down(conn->ip_address, "connected to");	/* receive loop */	while (1) {		iov.iov_len = ISCSI_HDR_LEN;		iov.iov_base = buffer;		/* receive iSCSI header */		err = iscsi_rx_data(conn, &iov, 1, ISCSI_HDR_LEN);		if (err != ISCSI_HDR_LEN) {			goto iscsi_rx_thread_out;		}		TRACE_BUFFER(TRACE_BUF, buffer, ISCSI_HDR_LEN,					 "%s Got PDU header\n", current->comm);		opcode = buffer[0] & ISCSI_OPCODE;		local_itt = ntohl(((struct generic_pdu *)buffer)->init_task_tag);		if (!(conn->session->tsih)) {			/* not in full feature phase yet, only accept Login request pdus */			if (opcode != ISCSI_INIT_LOGIN_CMND) {				TRACE_ERROR("%s ITT %u has opcode 0x%02x, expected 0x%02x\n",							current->comm, local_itt, opcode,							ISCSI_INIT_LOGIN_CMND);				/* MUST immediately terminate the connection */				goto iscsi_rx_thread_out;			}			TRACE(TRACE_ISCSI, "%s Got login request, ITT %u\n",				  current->comm, local_itt);			if (handle_login(conn, buffer) < 0) {				TRACE_ERROR("%s Trouble in handle_login\n", current->comm);				goto iscsi_rx_thread_out;			}			continue;		}		/* keep a copy of this header in case we need it in a later reject */		memcpy(conn->bad_hdr, buffer, ISCSI_HDR_LEN);		/* connection belongs to session that is in full feature phase */		if (conn->hdr_crc) {			/* read and check header digest on this pdu */			TRACE(TRACE_DEBUG, "iscsi_rx_thread: Header digest check\n");			hdr_crc = 0;			do_crc(buffer, ISCSI_HDR_LEN, &hdr_crc);			iov.iov_len = CRC_LEN;			iov.iov_base = &digest;			if ((err = iscsi_rx_data(conn, &iov, 1, CRC_LEN)) != CRC_LEN) {				goto iscsi_rx_thread_out;			}			if (hdr_crc != digest) {				TRACE_ERROR("%s Expected header crc 0x%08x, got 0x%08x\n",							current->comm, ntohl(hdr_crc), ntohl(digest));				/* Error Recovery Code Added by SAI */				TRACE(TRACE_ERROR_RECOVERY,					  "Start header digest error recovery\n");				err_rec.curr_conn = conn;				err_rec.pdu_hdr = (struct generic_pdu *)buffer;				err_rec.pdu_hdr->length = be32_to_cpu(err_rec.pdu_hdr->length);				err_rec.err_type = HEADER_DIGERR;				if ((err = targ_do_error_recovery(&err_rec)) < 0)					goto iscsi_rx_thread_out;				continue;			} else {				TRACE(TRACE_ISCSI_FULL, "Got header crc 0x%08x\n",					  ntohl(digest));			}		}		switch (opcode) {		case ISCSI_INIT_LOGIN_CMND:			{				/* got Login request while in full feature phase */				TRACE_ERROR("%s Got login request ITT %u in full feature "							"phase\n", current->comm, local_itt);				goto iscsi_rx_thread_out;			}		case ISCSI_INIT_TEXT_CMND:			{				TRACE(TRACE_ISCSI, "%s Got text request, ITT %u\n",					  current->comm, local_itt);				if (handle_text_request(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_text_request, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_INIT_SCSI_CMND:			{				TRACE(TRACE_ISCSI, "%s Got SCSI command, CmdSN %u, ITT %u\n",					  current->comm,					  ntohl(((struct generic_pdu *)buffer)->cmd_sn),					  local_itt);				if (handle_cmnd(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_cmnd, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_INIT_SCSI_DATA_OUT:			{				TRACE(TRACE_ISCSI, "%s Got data-out, ITT %u, offset %u\n",					  current->comm, local_itt,					  ntohl(((struct generic_pdu *) buffer)->offset));				if (handle_data(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_data, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_INIT_TASK_MGMT_CMND:			{				TRACE(TRACE_ISCSI,					  "%s Got task mgt command, ITT %u\n",					  current->comm, local_itt);				if (handle_task_mgt_command(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_task_mgt_cmnd, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_INIT_LOGOUT_CMND:			{				TRACE(TRACE_ISCSI, "%s Got logout request, ITT %u\n",					  current->comm, local_itt);				if (handle_logout(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_logout, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_INIT_NOP_OUT:			{				TRACE(TRACE_ISCSI, "%s Got NOP_OUT, ITT %u\n",					  current->comm, local_itt);				if (handle_nopout(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_nopout, ITT %u\n",								current->comm, local_itt);					goto iscsi_rx_thread_out;				}				break;			}			/* SNACK Handling by Target - SAI */		case ISCSI_INIT_SNACK:			{				TRACE(TRACE_ERROR_RECOVERY, "%s Got SNACK Request\n",					  current->comm);				if (handle_snack(conn, conn->session, buffer) < 0) {					TRACE_ERROR("%s Trouble in handle_snack\n", current->comm);					goto iscsi_rx_thread_out;				}				break;			}		case ISCSI_TARG_NOP_IN:		case ISCSI_TARG_SCSI_RSP:		case ISCSI_TARG_TASK_MGMT_RSP:		case ISCSI_TARG_LOGIN_RSP:		case ISCSI_TARG_TEXT_RSP:		case ISCSI_TARG_SCSI_DATA_IN:		case ISCSI_TARG_LOGOUT_RSP:		case ISCSI_TARG_R2T:		case ISCSI_TARG_ASYNC_MSG:		case ISCSI_TARG_RJT:			{				TRACE_ERROR("%s Initiator sent a target opcode %.2x, ITT %u\n",							current->comm, opcode, local_itt);				/*****				TRACE_SET(TRACE_DEBUG | TRACE_ISCSI | TRACE_ERROR_RECOVERY							  | TRACE_ISCSI_FULL | TRACE_ENTER_LEAVE);				*****/				/* Send a Reject PDU and escalate to session recovery */				enqueue_reject(conn, REASON_PROTOCOL_ERR);				targ_session_recovery(conn);				goto iscsi_rx_thread_out;			}		default:			{				TRACE_ERROR("%s Got unknown opcode %.2x, ITT %u\n",							current->comm, opcode, local_itt);				/*****				TRACE_SET(TRACE_DEBUG | TRACE_ISCSI | TRACE_ERROR_RECOVERY							  | TRACE_ISCSI_FULL | TRACE_ENTER_LEAVE);				*****/				/* Send a Reject PDU and escalate to session recovery */				enqueue_reject(conn, REASON_COMMAND_NOT_SUPPORTED);				targ_session_recovery(conn);				goto iscsi_rx_thread_out;			}		} /* switch */		/* in case there are any out-of-order commands that are now in-order */		check_queued_cmnd(conn->session);	} /* while(1) */iscsi_rx_thread_out:	conn->active = 0;	conn->rx_thread = NULL;	if (conn->tx_thread) {		/* tx thread still going, shut it down */		send_sig(ISCSI_SHUTDOWN_SIGNAL, conn->tx_thread, 1);	} else {		/* tx thread has shut down, if socket is still open, release it */		iscsi_release_socket(conn);	}	up(&conn->kill_rx_sem);	printk("%s Exiting pid %d\n", current->comm, current->pid);	return 0;}static voiddeal_with_nop_timer(unsigned long data);static voidrestart_nop_timer(struct iscsi_conn *conn){	conn->nop_timer.expires = jiffies + conn->nop_period;	conn->nop_timer.data = (unsigned long) conn;	conn->nop_timer.function = deal_with_nop_timer;	add_timer(&conn->nop_timer);}/* called by kernel when nop periodic timer expires on a connection * Always turn on the silence bit, * and also turn on the need nopin bit if silence bit was on before the set.*/static voiddeal_with_nop_timer(unsigned long data){	struct iscsi_conn *conn;	conn = (struct iscsi_conn *)data;	if (test_and_set_bit(SILENCE_BIT, &conn->control)) {		set_bit(NEED_NOPIN_BIT, &conn->control);	}	restart_nop_timer(conn);	if (atomic_read(&conn->tx_sem.count) <= 0) {		up(&conn->tx_sem);	}}/* * iscsi_tx_thread: This thread is responsible for the transmission of * responses and/or status information to the initiator */intiscsi_tx_thread(void *param){	struct iscsi_conn *conn = (struct iscsi_conn *) param;	struct iscsi_session *session;	struct iscsi_cmnd *cmnd, *prev_cmnd;	int count, skipover;#if defined(CONFIG_ISCSI_DEBUG)	__u32 save_mask;#endif	lock_kernel();/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else

⌨️ 快捷键说明

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