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

📄 initiator_utilities.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	space_left = current_session->oper_param->FirstBurstLength						- actual_immediate_data_length;	/* assume no unsolicited DataOut pdus will follow this one */	new_command->cmd_msg_flags = 0;	if (current_session->oper_param->InitialR2T		|| new_command->still_to_send == 0		|| space_left <= 0) {		/* set F bit as no separate unsolicted data PDUs can follow */		iscsi_cmd->flags |= F_BIT;	} else if (!(current_session->oper_param->InitialR2T)) {		/* we are allowed to send unsolicited data PDUs		 * after this command, but do we need to and		 * is there any burst space left to do so?		 */		if (new_command->still_to_send > 0 && space_left > 0) {			/* still data left to send, and there is room in first			 * burst, so set up to send unsolicited data PDUs next			 */			if ((cookie = create_r2t_cookie(current_session))								!= NULL) {				cookie->offset = new_command->data_offset;				cookie->r2t_xfer_length						= new_command->still_to_send;				if (new_command->still_to_send > space_left)					cookie->r2t_xfer_length = space_left;				hookup_r2t_cookie(cookie, current_session,		  				  current_connection,						  new_command, ALL_ONES);				/* tell tcp DataOut pdus follow */				new_command->cmd_msg_flags = MSG_MORE;				/* need to mark this in case of retransmission,				 * because xmitting the cookie will overwrite				 * the command iovector and both will have				 * to be set up again.				 */				new_command->cmd_state = CMD_STATE_REXMIT_ORIG;			}		}	}	/* fill in fields for tx thread */	new_command->tx_sent_so_far = 0;	/* nothing sent so far */	new_command->retransmit_tx_size = new_command->tx_size;	new_command->header_complete = 0;	/* need to finish header */	/* These are used in do_tx_send() and rx_rsp(), both of which will not	 * see this until after we set them here.	 */	new_command->header_opcode = ISCSI_INIT_SCSI_CMND;	new_command->header_flags = iscsi_cmd->flags;out:	/* set the number of iov slots actually used */	new_command->tx_iovlen = count;	if (unlikely(max_iov_count < count))		max_iov_count = count;	/* keep track of max no. ever used */}/* * executed only by tx thread. * the session->sess_lock MUST be held by the calling process/thread. * * Called only from ready_to_xmit(). * At the time of the call, cookie is known to be first on related_command's * r2t_cookies list, it is known to be non-NULL, it is known to be at the * beginning of related_connection's order_link, and it is known to * have a positive xfer length. * * Called to build a DataOut pdu header in the "data" area of the * "related_command" if that area is currently unused (else does nothing). * The amount of data to send is controlled by the first "cookie" for * that command, but the location(s) and layout of the data in memory * are controlled by the SCpnt field in the "related_command" when * setting up the msghdr and io vector in the "related_command". * Returns number of bytes newly set up for transmission (0 if none). * * While writing, the following variables in the related_command maintain state: *	tx_size			number of bytes left to send in current xmission *				(updated as each pdu is sent) *	tx_sent_so_far		number of bytes sent so far in current xmission *				(updated as each pdu is sent) *	retransmit_size		number of original bytes in current xmission *	still_to_send		total number of bytes of data not yet sent for *				this write command *				(updated as each pdu is sent) *	r2t_sn			R2TSN expected in next R2T from target *	data_offset		offset expected in next in-order R2T from target *				(updated as each R2T is received) *	n_r2t_cookies		number of elements in list r2t_cookies that were *				created by R2Ts (excludes cookie created for *				unsolicited DataOut pdus) *				(1 cookie created as each R2T is received) *	r2t_cookes		list with 1 r2t_cookie for each unsatisfied R2T *				(includes 1 r2t_cookie for any unsolicited pdus) *				(cookies removed from list as satisfied) *	header_opcode		opcode of last command sent carrying data *				(0x01 on WRITE, 0x05 for DataOut) *	data			area where DataOut pdu is built */intsetup_dataoutpdu(struct connection *related_connection,		 struct command *related_command,		 struct r2t_cookie *cookie){	int len, prev_offset, cur_offset, count, size;	char *cur_ptr;	struct iovec *iov;	struct scatterlist *sg;	struct session *related_session;	int sglength;	TRACE(TRACE_ENTER_LEAVE, "Enter setup_dataoutpdu\n");	size = 0;	if (related_command->tx_size != 0) {		/* command's single data slot is busy, don't overwrite it */		TRACE(TRACE_ISCSI_FULL,		      "Busy DataOut slot, ITT %u,  tx_size %u\n",		      related_command->init_task_tag, related_command->tx_size);		goto out;	}	/* set up the DataOut PDU in command's single data slot */	memset(&related_command->data, 0, ISCSI_HDR_LEN);	related_command->data.opcode = ISCSI_INIT_SCSI_DATA_OUT;	related_command->data.target_xfer_tag = cookie->target_xfer_tag;	related_command->data.init_task_tag				= htonl(related_command->init_task_tag);	related_command->data.exp_stat_sn				= htonl(related_connection->exp_stat_sn);	related_command->data.data_sn = htonl(cookie->data_out_sn);	/* assume this is not the last DataOut PDU to be	 * sent in this sequence	 */	related_session = related_connection->my_session;	len = related_connection->max_send_length;	if (cookie->r2t_xfer_length <= len) {		/* bad assumption, this is last DataOut PDU in this seq */		len = cookie->r2t_xfer_length;		related_command->data.flags |= F_BIT;	}	/* assume no DataOut pdus follow this one */	related_command->cmd_msg_flags = 0;	related_command->tx_data_length = len;		/* for tx stats */	related_command->data.length = htonl(len);	related_command->still_to_send -= len;	/* get offset into original SCSI CMD buffer of next byte to be sent */	if (unlikely(related_session->oper_param->DataPDUInOrder == 0)) {		/* DataPDUInOrder==No, send Data Out PDUs backwards */		cookie->offset -= len;		/* next Data Out PDU limit */		prev_offset = cookie->offset;	/* this Data Out PDU offset */	} else {		/* DataPDUInOrder==Yes, send Data Out PDUs in order */		prev_offset = cookie->offset;	/* this Data Out PDU offset */		cookie->offset += len;		/* next Data Out PDU offset */	}	related_command->data.offset = htonl(prev_offset);	TRACE(TRACE_DEBUG,	      "Setup DataOut PDU, offset %d, DSL %d, still_to_send %u\n",	      prev_offset, len, related_command->still_to_send);	/* update values in related command cookie to account for this PDU */	cookie->data_out_sn++;			/* Seqno of next Data Out PDU */	cookie->r2t_xfer_length -= len;		/* total amount left to send */	if (((int)cookie->r2t_xfer_length) <= 0) {		/* finished with this cookie */		free_r2t_cookie(related_connection, related_command, cookie);	}	/* set up the TCP io vector, beginning with no. of bytes to xfer */	size = related_connection->basic_hdr_len + len;	iov = related_command->tx_iov;		/* point at empty tx_iov[] */	/* DataOut pdu header built in separate "data" area of struct command */	iov->iov_len = related_connection->basic_hdr_len;	iov->iov_base = &related_command->data;	related_command->header_complete = 0;	related_command->header_opcode = related_command->data.opcode;	related_command->header_flags = related_command->data.flags;#ifdef K26	if (use_sendpage(related_connection, related_command)) {		related_command->pindex = 0;		related_command->padding = 0;	}#endif	/* now fill in the iovector to point to data to be sent */	iov++;	count = 2;		/* always at least 2 items in iovector */	related_command->data_checksum = 0;	/* initialize data checksum */	if (related_command->SCpnt->use_sg > 0) {		/* SCSI gave us a scatter-gather list */		sg = (struct scatterlist *) related_command->SCpnt							->request_buffer;		cur_offset = 0;#ifdef K26		/* Convert page struct passed in SG		 * to kernel vaddr. We can sleep on this		 * call so have to release our lock.		 */		UNH_UNLOCK(&related_session->sess_lock,				related_connection->tx_lock_flags);		sg_dma_address(sg) = (dma_addr_t)kmap(sg->page);		UNH_LOCK(&related_session->sess_lock,				related_connection->tx_lock_flags);		cur_ptr = (void *)sg_dma_address(sg);#else		cur_ptr = sg->address;#endif		/* skip thru scatterlist past data already sent */		while (cur_offset < prev_offset) {#ifdef K26			sglength = sg_dma_len(sg);#else			sglength = sg->length;#endif			if (cur_offset + sglength > prev_offset) {				cur_ptr = cur_ptr + (prev_offset - cur_offset);				cur_offset = prev_offset;			} else {				cur_offset += sglength;				sg++;#ifdef K26				cur_ptr =  (void *)sg_dma_address(sg);#else				cur_ptr = sg->address;#endif			}		}		/* sg now points at first list item to xfer */#ifdef K26		iov->iov_len = ((char *)(sg_dma_address(sg) + sg_dma_len(sg)))				- cur_ptr;		if (use_sendpage(related_connection, related_command)) {			int offset = cur_ptr - (char *) sg_dma_address(sg);			related_command->sg[related_command->pindex] = *sg;			related_command->sg[related_command->pindex].length -= offset;			related_command->sg[related_command->pindex].offset += offset;			related_command->pindex++;		}#else		iov->iov_len = (sg->address + sg->length) - cur_ptr;#endif		iov->iov_base = cur_ptr;		sg++;		len -= iov->iov_len;	/* no. of bytes left to fill */		while (len > 0) {			/* need to add another element in iovector, but first			 * compute the partial data digest if we are using them			 */			if (related_connection->connection_flags				& USE_DATADIGEST) {				do_crc(iov->iov_base, iov->iov_len,				       &related_command->data_checksum);			}			count++;			iov++;#ifdef K26			iov->iov_base = (unsigned long *)sg_dma_address(sg);			sglength = sg_dma_len(sg);			if (use_sendpage(related_connection, related_command)) {				related_command->sg[related_command->pindex]						= *sg;				related_command->pindex++;			}#else			iov->iov_base = sg->address;			sglength = sg->length;#endif			iov->iov_len = sglength;			len -= sglength;			sg++;		}		if (len < 0) {			/* only need to send part of the last list item */			iov->iov_len += len;		}	} else {		/* all the data is in one buffer (no scatter gather list) */		iov->iov_base			= related_command->SCpnt->request_buffer + prev_offset;		iov->iov_len = len;	}	/* now deal with any padding that is needed.	 *	 * Draft 20, Section 10.1 iSCSI PDU Length and Padding	 * "iSCSI PDUs are padded to the closest integer number of four byte	 * words.  The padding bytes SHOULD be 0."	 */	len = (-size) & 3;	if (unlikely(len != 0)) {		/* need to send len pad bytes in another element in iovector		 * but first compute the partial data digest if we are		 * using them		 */		if (related_connection->connection_flags & USE_DATADIGEST) {			do_crc(iov->iov_base, iov->iov_len,			       &related_command->data_checksum);		}		count++;		iov++;		iov->iov_base = &pad_bytes;		iov->iov_len = len;		size += len;	/* is now a multiple of 4 */		TRACE(TRACE_ISCSI_FULL, "Attach %d pad bytes\n", len);#ifdef K26		if (use_sendpage(related_connection, related_command))			related_command->padding = len;#endif	}	/* now compute and add the final data digest if we are using them */	if (related_connection->connection_flags & USE_DATADIGEST) {		do_crc(iov->iov_base, iov->iov_len,		       &related_command->data_checksum);		count++;		iov++;		iov->iov_base = &related_command->data_checksum;		iov->iov_len = CRC_LEN;		size += CRC_LEN;		TRACE(TRACE_ISCSI_FULL, "Attach DataDigest\n");	}	/* finally save size and number of iovector elements in message header*/	related_command->tx_sent_so_far = 0;	/* nothing sent yet */	related_command->tx_size = size;	/* marks this "in use" */	/* in case of rexmit only */	related_command->retransmit_tx_size = size;	related_command->tx_iovlen = count;	/* no. of iovs used */	if (unlikely(max_iov_count < count)) {		max_iov_count = count;	}	related_command->tx_wait_to_send = jiffies;	/* can send it now */	if (!list_empty(&related_connection->r2t_list)) {		/* tell tcp more DataOut pdus are ready to follow this one */		related_command->cmd_msg_flags = MSG_MORE;	}out:	TRACE(TRACE_ENTER_LEAVE, "Leave setup_dataoutpdu, size %u\n", size);	return size;}/* "prints" statistics on iov usage into buf, * returns no. of chars printed. */intprint_iovs(char *buf){	if (buf == NULL)		return printk("iscsi Maximum of %d iov slots used out of %d\n",			      max_iov_count, MAX_IOV_SLOTS);	else		return sprintf(buf, "Maximum of %d iov slots used out of %d\n",			       max_iov_count, MAX_IOV_SLOTS);}voidendup_iovs(void){	print_iovs(NULL);}/* * executed only by rx thread. * the session->sess_lock MUST be held by the calling process/thread. * Called from recv_data_in_data(), recv_pdu_header(). * Reads "orig_size" bytes into the iovector already set up in conn->rx_iov * from the socket attached to "conn".  Uses the rx_msg and rx_iov * structures attached to "conn" to control the read. * "orig_size" MUST be positive. * Returns > 0 ("orig_size") on success with session lock held, *	   < 0 on failure with session lock not held.*/static int __attribute__ ((no_instrument_function))recv_iovector(struct connection *conn, int orig_size, int iov_count){

⌨️ 快捷键说明

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