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

📄 initiator_utilities.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int retval;	struct msghdr *msg;	mm_segment_t oldfs;	struct session *session = conn->my_session;	char ip_string[INET6_ADDRSTRLEN+2], port_string[8];#if defined(CONFIG_ISCSI_DEBUG)	struct iovec *iov, *iov_copy = NULL;	int index;#endif	TRACE(TRACE_ENTER_LEAVE, "Enter recv_iovector, orig_size %d, "		"iov_count %d\n", orig_size, iov_count);	if (conn->connection_flags & CONN_HIT_EOF) {		/* previously hit EOF on this connection, don't read again */		retval = -ECONNRESET;		goto out_lock_held;	}	/* set up this connection's reusable message header.	 * NOTE: sock_recvmsg() destroys some part of this header,	 *	 so it MUST be set up EACH TIME through here.	 */	msg = &conn->rx_msg;	memset(msg, 0, sizeof(struct msghdr));	/* most fields are 0/NULL */	msg->msg_iovlen = iov_count;	msg->msg_iov = conn->rx_iov;	if (unlikely(max_iov_count < iov_count)) {		/* keep track of max no. of iov slots ever used */		max_iov_count = iov_count;	}#if defined(CONFIG_ISCSI_DEBUG)	if (unlikely(TRACE_TEST(TRACE_BUF))) {		TRACE(TRACE_BUF, "sock_recvmsg waiting for %d bytes\n",			orig_size);		iov = conn->rx_iov;		for (index = 0; index < iov_count; index++ ) {			TRACE(TRACE_DEBUG,				"index %x iov base %p iov size %d \n", 				index, iov->iov_base, iov->iov_len); 			iov++;		}		index *= sizeof(struct iovec);		iov_copy = my_kmalloc(index, "iov_copy");		if (likely(iov_copy != NULL)) {			memcpy(iov_copy, conn->rx_iov, index);		}	}#endif	/* allow other threads to run in case we block in the receive */	UNH_UNLOCK(&session->sess_lock, conn->rx_lock_flags);	oldfs = get_fs();	set_fs(get_ds());	retval = sock_recvmsg(conn->sock, msg, orig_size, MSG_WAITALL);	set_fs(oldfs);	UNH_LOCK(&session->sess_lock, conn->rx_lock_flags);	TRACE(TRACE_DEBUG, "sock_recvmsg got %d bytes\n", retval);	if (unlikely(retval != orig_size)) {		/* sock_recvmsg hit an error or end of file */		if (retval == 0 || retval == -ECONNRESET) {			/* got an EOF indication, which means remote				peer is gone */			if (cnv_inet_to_string(conn->ip_address, ip_string,					port_string) > 0) {				TRACE_ERROR("%s end-of-file from %s:%s\n",					    current->comm, ip_string,					    port_string);			}			conn->connection_flags |= CONN_HIT_EOF;			retval = -ECONNRESET;			goto out_lock_held;		}		if (retval != -ERESTARTSYS) {			TRACE_ERROR("sock_recvmsg expected %d bytes, got %d\n",				    orig_size, retval);		}		if (retval > 0) {			/* to tell caller "lock not held" */			retval = -ECONNRESET;		}		goto out_lock_held;	}#if defined(CONFIG_ISCSI_DEBUG)	if (unlikely(TRACE_TEST(TRACE_BUF))) {		if ((iov = iov_copy)) {			for (index = 0; index < iov_count; index++) {				dump_buffer(iov->iov_base, iov->iov_len);				iov++;			}		}	}#endifout:#if defined(CONFIG_ISCSI_DEBUG)	my_kfree((void **)&iov_copy, "iov_copy");#endif	TRACE(TRACE_ENTER_LEAVE, "Leave recv_iovector, retval %d\n", retval);	return retval;out_lock_held:	UNH_UNLOCK(&session->sess_lock, conn->rx_lock_flags);	goto out;}/* * executed only by rx thread. * the session->sess_lock MUST be held by the calling process/thread. * Called from init_recovery_thread(), iscsi_initiator_rx_thread(). * Reads an iscsi pdu header into conn->rx_buf from conn->sock. * The header length is 48 without header digests, 52 bytes with. * Uses rx_msg and rx_iov structures in "conn" to control the read. * Returns > 0 (header length 48 or 52) on success with session lock held, * 	   < 0 on failure with session lock not held. */intrecv_pdu_header(struct connection *conn){	int size;	struct iovec *iov;	size = conn->basic_hdr_len;	/* set up this connection's reusable i/o vector to point at base.	 * NOTE: sock_recvmsg() destroys some part of this header,	 *	 so it MUST be set up EACH TIME through here.	 */	iov = conn->rx_iov;	iov->iov_len = size;	iov->iov_base = conn->rx_buf;	return recv_iovector(conn, size, 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 is responsible for making the checks for exp_cmd_sn and * max_cmd_sn values in the received iSCSI header from the target. * Parameters:	exp_cmd_sn from the PDU (in host byte order) *		max_cmd_sn from the PDU (in host byte order) *		cur_session, pointing to the struct session * Return value: 0, if the exp_cmd_sn and max_cmd_sn are valid *		-1, if either exp_cmd_sn or max_cmd_sn is invalid. ****************************************************************************/int __attribute__ ((no_instrument_function))check_and_update_cmd_sns(__u32 exp_cmd_sn, __u32 max_cmd_sn,			 struct session *cur_session){	int retval = 0, delta;	struct connection *conn;	TRACE(TRACE_ENTER_LEAVE, "Enter check_and_update_cmd_sns\n");	/* RFC 3720 Section 3.2.2.1 Command Numbering and Acknowledging	 *	 * "Comparisons and arithmetic on ExpCmdSN and MaxCmdSN MUST use	 * Serial Number Arithmetic as defined in [RFC1982] where	 * SERIAL_BITS = 32.	 *	 * The target MUST NOT transmit a MaxCmdSN that is less than ExpCmdSN-1.	 * ...	 *	 * MaxCmdSN and ExpCmdSN fields are processed by the initiator as	 * follows:	 *	 * - If the PDU MaxCmdSN is less than the PDU ExpCmdSN-1 (in Serial	 *   Arithmetic Sense), they are both ignored.	 *	 * - If the PDU MaxCmdSN is greater than the local MaxCmdSN (in Serial	 *   Arithmetic Sense), it updates the local MaxCmdSN; otherwise,	 *   it is ignored.	 *	 * - If the PDU ExpCmdSN is greater than the local ExpCmdSN (in Serial	 *   Arithmetic Sense), it updates the local ExpCmdSN; otherwise,	 *   it is ignored.	 *	 * This sequence is required because updates may arrive out of order	 * (e.g., the updates are sent on different TCP connections).	 *	 * iSCSI initiators and targets MUST support the command numbering	 * scheme."	 */	delta = max_cmd_sn - (exp_cmd_sn - 1);	if (delta < 0) {		/* MaxCmdSN < ExpCmdSN - 1, ignore both PDU values */		TRACE(TRACE_ISCSI_FULL,		      "Ignoring PDU's ExpCmdSN %u and MaxCmdSN %u\n",		      exp_cmd_sn, max_cmd_sn);	} else {		/* values in the PDU are ok relative to each other */		delta = max_cmd_sn - cur_session->max_cmd_sn;		if (delta < 0) {			/* PDU.MaxCmdSN < local.MaxCmdSN, ignore				PDU's MaxCmdSN */			TRACE(TRACE_ISCSI_FULL, "Ignoring PDU's MaxCmdSN %u\n",			      max_cmd_sn);		} else if (delta > 0) {			/* MaxCmdSN just increased, update the local MaxCmdSN */			cur_session->max_cmd_sn = max_cmd_sn;			/* find tx_threads waiting for this limit to increase */			for (conn = cur_session->connection_head;			     conn != NULL;			     conn = conn->next) {				if (conn->connection_flags & NEED_TX_WAKEUP) {					/* yes, so wake it up!! */					if (atomic_read(&conn->tx_sem.count)						<= 0) {						TRACE(TRACE_ISCSI_FULL,					      "rx_thread: wake up tx_thread\n");						up(&conn->tx_sem);					}				}			}		}		delta = exp_cmd_sn - cur_session->exp_cmd_sn;		if (delta < 0) {			/* PDU.ExpCmdSN < local.ExpCmdSN,				ignore PDU's ExpCmdSN */			TRACE(TRACE_ISCSI_FULL, "Ignoring PDU's ExpCmdSN %u\n",			      exp_cmd_sn);		} else if (delta > 0) {			/* greater than, check it against local CmdSN */			delta = cur_session->cur_cmd_sn - exp_cmd_sn;			if (delta < 0) {				TRACE_ERROR				    ("Got ExpCmdSN %u, exceeds next CmdSN %u\n",				     exp_cmd_sn, cur_session->cur_cmd_sn);				retval = -1;			} else {				/* not less than, update the local ExpCmdSN */				cur_session->exp_cmd_sn = exp_cmd_sn;			}		}	}	TRACE(TRACE_ENTER_LEAVE, "Leave check_and_update_cmd_sns, retval %d\n",	      retval);	return retval;}/* * the session->sess_lock MUST be held by the calling process/thread. * Calls SCSI Mid-level's scsi_done callback with result, * (and with session->lock held). * Then frees up storage allocated to old command after * both tx_thread and tx_thread have completed using the command. * * Note - The use of RXDONE and TXDONE flags syncronizes the freeing * to the command structure in an SMP environment under the * protection of session->lock. */voidfree_pending_command(struct command *old_command,		     struct connection *current_connection){	struct scsi_cmnd *SCpnt;#if defined(CONFIG_ISCSI_DEBUG)	__u32 local_itt = old_command->init_task_tag;#endif	struct r2t_cookie *cookie;	struct list_head *lptr, *next;	TRACE(TRACE_ENTER_LEAVE, "Enter free_pending_command %p, ITT %u\n",	      old_command, local_itt);	if ((old_command->cmd_state & (CMD_STATE_RXDONE | CMD_STATE_TXDONE))	    != (CMD_STATE_RXDONE | CMD_STATE_TXDONE)) {		/* both rx and tx threads have not yet signed		 * off on this command		 */		goto out;	}	/* remove this command from this connection's pending command list */	list_del(&old_command->link);	/* release storage occupied by any range list used by this command */	free_range_list(&old_command->r2t_range_list);	/* free up any r2t cookies still pending for this command */	list_for_each_safe(lptr, next, &old_command->r2t_cookies) {		list_del(lptr);		cookie = list_entry(lptr, struct r2t_cookie, link);		uncreate_r2t_cookie(cookie, current_connection->my_session);	}	/* free up any buffer associated with this command */	my_kfree(&old_command->buffer_to_free, "NopOut/Text data");	/* get pointer to SCSI midlevel command */	SCpnt = old_command->SCpnt;	/* put old command structure on end of session's free list */	endup_command(old_command, current_connection->my_session);#ifdef K26	/* free up kmappings we did 	 * if we had scatter-gather list filled 	 */	if (SCpnt != NULL && SCpnt->use_sg != 0) {		/* We filled a scatter-gather list with kmap'ings */		int i =  SCpnt->use_sg;		struct scatterlist *sg  = (struct scatterlist *)		     SCpnt->request_buffer;		while (i --) {			TRACE(TRACE_DEBUG,				"Unmapping %d  page %p for sg_dma_address(sg) %x\n",				i, sg->page,sg_dma_address(sg));			kunmap(sg->page);			sg ++;		}	}#endif /* K26 */	if (SCpnt != NULL && SCpnt->scsi_done != NULL) {		/* post to SCSI midlevel that this command completed */		call_back_scsi_done(SCpnt);		TRACE(TRACE_DEBUG, "Posted completion, ITT %u\n",		      local_itt);	}out:	TRACE(TRACE_ENTER_LEAVE, "Leave free_pending_command\n");}voidalloc_inquiry_stuff(struct session *sess, __u32 lun, int size){	if ((sess->inquiry_buf[lun] = my_kmalloc(size, "inquiry_buf"))) {		sess->inquiry_size[lun] = size;	}}voidfree_inquiry_stuff(struct session *sess, __u32 lun){	my_kfree((void **)&sess->inquiry_buf[lun], "inquiry_buf");	sess->inquiry_size[lun] = 0;}/* we just successfully completed an inquiry command */voidsave_inquiry(struct session *sess, struct command *related_command, int missing){	int slength;	__u32 lun;	slength = related_command->SCpnt->request_bufflen;	TRACE(TRACE_DEBUG, "completed inquiry, slength %d, missing %d\n",		slength, missing);	if (missing > 0)		slength -= missing;	if (slength > 0) {#ifdef K26		lun = related_command->SCpnt->device->lun;#else		lun = related_command->SCpnt->lun;#endif		if (sess->inquiry_size[lun] < slength) {			free_inquiry_stuff(sess, lun);		}		if (!sess->inquiry_buf[lun]) {			alloc_inquiry_stuff(sess, lun, slength);		}		if (sess->inquiry_buf[lun]) {			memcpy(sess->inquiry_buf[lun],				related_command->SCpnt->request_buffer,				slength);			if (unlikely(TRACE_TEST(TRACE_BUF))) {				TRACE(TRACE_BUF, "inquiry_buf for lun %u, %d "					"bytes\n", lun, slength);				dump_buffer(sess->inquiry_buf[lun], slength);			}		}	}}/* we just successfully completed a read capacity command */voidsave_capacity(struct session *sess, struct command *related_command, int missing){	int slength;

⌨️ 快捷键说明

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