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

📄 overview-ffp

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻
📖 第 1 页 / 共 3 页
字号:
	2.	the "cmnd" field which contains all the information needed by the target		to perform the SCSI operation.  (This is usually called the "CDB", for		"Command Description Block".) This field contains the information		needed by the SCSI system on the target to perform the SCSI operation.		It includes an "opcode" value of 0x28 for READ (10), a "lun" value		(which duplicates the lun field mentioned next), the "logical block		address" value (i.e., the number of the logical block on the disk where		this read starts), the "length" value, which is the "request_bufflen"		field (mentioned next) divided by 512 (i.e., the number of logical		blocks to read, each logical block being 512 bytes), and finally a		"control" value.	3.	the "lun" field which contains the "Logical Unit Number" used by SCSI		to identify devices.  This value duplicates a field in the CDB.	4.	the "request_bufflen" field which contains the total number of bytes of		data to be read (i.e., transfered from the target) by this command.		This value is 512 times the value of a field in the CDB.	5.	the "request_buffer" field, which indicates where in memory SCSI		expects the data to be put as it is read from the target.		6.	the "use_sg" field, which is 0 if the "request_buffer" field is the		address in memory of the data buffer itself, and which is greater than		0 if the "request_buffer" field is the address in memory of a		scatter-gather list containing "use_sg" data buffers.	7.	the "sc_data_direction" field, which is 1 if the command is generally		categorized as a "write" command (i.e., if any data flows during this		command, it will be from initiator to target), and which is 2 if the		command is generally categorized as a "read" command (i.e., if any data		flows during this command, it will be from target to initiator).	8.	the "result" field, which is filled in by the initiator when it has		finished processing this command completely.  The values that can be		stored here are defined by SAM2.  The value 0 means "GOOD".  The		others are various error codes which are defined as DID_XXX symbols		in the file /usr/src/linux/drivers/scsi/scsi.h.  (DID_OK is defined		as 0.)  The initiator will fill this field by opaquely copying the		value in the Status field of a SCSIResponse PDU.  See section 3.4.2		of draft 9 for a partial listing of these values.5.1.3.2	struct command	The "iscsi_initiator_queuecommand" function creates a new "struct command"	data structure, initializes the fields, and adds it to the	"pending_commands" list for the current connection.  The "struct command"	contains a number fields that are initialized at this time.  Since we	are considering a READ operation, only those fields relevant to a READ are	discussed here.	1.	the "SCpnt" field, which is initialized with a pointer to the		"Scsi_Cmnd" structure.	2.	the "init_task_tag" field, which is initialized with value of the		session-wide "init_task_tag".  This value will be put into all PDUs		sent/received during the processing of this command, as discussed		above.	3.	the "recvd_length" field, which is initialized to 0 and will be used by		the initiator to keep track of the number of bytes of data received in		one burst or sequence of DataIn PDUs.	4.	the "data_offset" field, which is initialized to 0 and will be used by		the initiator to keep track of where in its memory buffer to put the		bytes of data received from the next DataIn PDU.	5.	the "data_in_sn" field, which is initialized to 0 and will be used by		the initiator to check the DataSN field of all DataIn PDUs sent by the		target, as discussed above.5.1.3.3	SCSI Command PDU	"iscsi_initiator_queuecommand" then sets up the header of the "SCSI	Command" PDU in the "iscsi_cmd" field of the "struct command".  This	header contains the following fields:		opcode 0x01,		I bit 0		F bit 1		R bit 1 (for read)		W bit 0 (no write)		DSL 0 (no data in this PDU)		the LUN copied from the "lun" field in the "Scsi_Cmnd" (see above),		the ITT for this task (see above),		the EDTL copied from the "request_bufflen" field in the "Scsi_Cmnd"			(see above),		the CmdSN for this command (see above),		the ExpStatSN for this PDU (see above),		the CDB copied from the "cmnd" field in the "Scsi_Cmnd" (see above),	"iscsi_initiator_queuecommand" then attaches this newly initialized	"struct command" to the end of the "pending_commands" list for this	connection, and then does an "up" operation on the "tx_sem" semaphore for	the session in order to signal the "tx_thread" that a PDU is ready for	transmission to the target.5.1.4	Tx_Thread	Each iSCSI session contains one kernel thread that performs all	transmissions of PDUs to the target.  This thread consists of an infinite	loop that:		1.	blocks on a "down" operation on the "tx_sem" semaphore for this session		until some other process or thread does a corresponding "up" on this		semaphore to indicate that a PDU is ready for transmission to the		target.	2.	for each connection open in this session, search its pending command		list to see if there are any PDUs ready to be sent to the target.	3.	for each PDU ready to be sent to the target, call "sock_sendmsg" to		send it out over an open TCP connection to the target.	4.	after a PDU has been sent, set its "tx_size" field to 0 to indicate		that it has been sent.	5.	after all PDUs for all connections in the session have been sent,		return to step 1.	Note that when a PDU is sent, tx_thread does not remove it from the	"pending_commands" list for a connection because the information about the	command must be retained until the initiator receives a response from the	target.5.1.5	Rx_Thread	Each iSCSI connection contains one kernel thread that performs all	receptions of PDUs from the target.  This thread consists of an infinite	loop that:	1.	Blocks on a call to sock_recvmsg waiting for the target to send a PDU		to the initiator.  This call reads only the header of this PDU into		an rx_buf allocated to this connection.	2.	Uses the opcode field in the PDU header to call the appropriate		function to deal with PDUs of this type.  If the opcode is 0x25		(DataIn) then the function rx_data is called.  If the opcode is		0x21 (SCSIResponse) then the function rx_rsp is called.	3.	When the PDU has been processed by the appropriate function, return		to step 1.5.1.5.1	rx_data	This function is called whenever the header for a DataIn PDU has been	read in the rx_thread loop.  This function does the following:	1.	Search the list of pending commands associated with this connection		to find one whose init_task_tag field matches the ITT field in the		DataIn PDU.  It is an error if no such command is found.	2.	Extract the values from the BufferOffset and DSL fields in the DataIn		PDU and check that the BufferOffset value in the DataIn PDU matches the		data_offset value for this command, that the DSL field in the DataIn		PDU does not exceed the value in the MaxRecvPDULength key sent by the		initiator to the target, and that the total amount of data received		by this command, including the data in this PDU, does not exceed the		request_bufflen for this command.	3.	Check that the DataSN value in the DataIn PDU matches the data_in_sn		field of the command.	4.	If all the checks are ok, increment the data_in_sn value for this		command by 1, and the data_offset value for this command by the DSL		value.	5.	Finally, call sock_recvmsg to read the data attached to the DataIn		PDU directly into the memory location indicated by the request_buffer		field of the SCSI command (no extra copy required).5.1.5.2	rx_rsp	This function is called whenever the header for a SCSIResponse PDU has been	read in the rx_thread loop.  This function does the following:	1.	Search the list of pending commands associated with this connection		to find one whose init_task_tag field matches the ITT field in the		SCSIResponse PDU.  It is an error if no such command is found.	2.	Check that the F-bit is set to 1 (required for a SCSIResponse PDU).	3.	Check that the StatSN in the PDU matches the exp_stat_sn field		for this connection and then increment the exp_stat_sn field by 1.	4.	Check that the ExpCmdSn in the PDU matches the cmd_sn field for this		connection.	5.	Check that the O-bit (Overflow), U-bit (Underflow) and Residual Count		fields agree with the request_bufflen of the original command and		the data_offset (which gives the amount of data actually transfered).	6.	Store the Status value from the PDU into the result field of the SCSI		command, then call the SCSI Mid-level "done" function for this command.	7.	Remove this command from the list of pending commands for this		connection because it has now been completely processed.5.1.6	Using MaxBurstSize	The above discussion ignored the value of the key MaxBurstSize negotiated	during login.  However, this cannot be ignored, because DataIn PDUs must	be sent by the target in bursts or sequences having no more than	MaxBurstSize total bytes.  Therefore, one READ command requiring more data	than can be transfered in a single burst will be handled slightly	differently that the "simple" READ involving only one burst that was	discussed above.  This large READ command will require the transfer of	several bursts or sequences, each of which will contain several DataIn PDUs	as follows:	1.	one "SCSI Command" PDU sent by the initiator to deliver the READ		command information to the target,	2.	some number of "DataIn" PDUs sent back by the target to deliver the		data in the first burst to the initiator,	3.	some number of "DataIn" PDUs sent back by the target to deliver the		data in the second burst to the initiator,	...	4.	some number of "DataIn" PDUs sent back by the target to deliver the		data in the last burst to the initiator,	5.	one final "SCSI Response" PDU sent back by the target to deliver the		final status to the initiator.	Notice that there is no pause between bursts, and no extra PDU sent from	either initiator or target to indicate the end of one burst or the	beginning of another burst.  It is all based on the F-bit in the DataIn	PDUs.  If we assume a burst contains N DataIn PDUs, then the F-bit in	the first N-1 DataIn PDUs of the burst will have the F-bit set to 0,	and the last (Nth) DataIn PDU of the burst will have the F-bit set to 1.	Furthermore, the DataSN field in the DataIn PDUs is a counter that starts	with 0 for the first DataIn PDU in the first burst, and increments by 1	for each successive DataIn PDU in this command, regardless of which burst	the DataIn PDU belongs to!  In other words, the DataSN field does not get	reset to 0 for the first DataIn PDU of each burst -- it continues	incrementing across burst boundaries, as if these boundaries did not exist.5.1.6.1	PDU trace	The following gives an abbreviated trace of the PDUs sent during a READ	command that requires the transfer of 102400 bytes (200 blocks of 512	bytes each) from the target to the initiator.	(This is taken directly from the file "ty4" starting at line 1190.)	Assumptions:		1.	The command is a READ of 102400 bytes of data (200 blocks each			containing 512 bytes).		2.	The key MaxBurstSize=32768 was negotiated during login.		3.	As above, the key MaxRecvPDULength=12288 was negotiated during			login.	Since each burst or sequence can contain at most MaxBurstSize=32768 bytes	(64 logical blocks), the total READ of 102400 bytes (200 logical blocks)	will require at least 4 bursts -- the first 3 bursts will each contain	32768 bytes (64 logical blocks), for a total of 98304 bytes (192 logical	blocks); the fourth burst will contain the remaining 4096 bytes (8 logical	blocks) to give the required total of 102400 bytes (200 logical blocks).	Because a single DataIn PDU can contain at most MaxRecvPDULength=12288	bytes (24 logical blocks), the first 3 bursts will each contain 3 DataIn	PDUs -- the first 2 DataIn PDUs will each have the F-bit set to 0 and will	contain 12288 bytes (24 logical blocks), for a total of 24576 bytes (48	logical blocks); the third DataIn PDU will have the F-bit set to 1 and will	contain the remaining 8192 bytes (16 logical blocks) in the burst, giving a	total of 32768 bytes (64 logical blocks) for the burst.  The last burst	will consist of a single DataIn PDU containing 4096 bytes (8 logical	blocks) of data.	This is a grand total of 10 DataIn PDUs, and the DataSN field in these PDUs	will increase linearly from 0 to 9, without regard to the boundaries	between bursts (which is marked by the F-bit set to 1).	The complete sequence of PDUs for this operation follows (note that all	these PDUs carry the same ITT = 88905, and all the PDUs sent by the	target contain ExpCmdSN=22239):	Initiator->Target		Opcode = 0x01;  F = 1;  R = 1;  DSL = 0;  EDTL = 102400;			CmdSN = 22238;  ExpStatSN = 41			Target -> Initiator		Opcode = 0x25;  F = 0;  DataSN = 0;  DSL = 12288;  Buffer Offset = 0			First DataIn PDU of first burst (12288 bytes total so far)		Opcode = 0x25;  F = 0;  DataSN = 1;  DSL = 12288;  Buffer Offset = 12288			Second DataIn PDU of first burst (24576 bytes total so far)		Opcode = 0x25;  F = 1;  DataSN = 2;  DSL = 8192;  Buffer Offset = 24576			Third (last) DataIn PDU of first burst (32768 bytes total so far)		Opcode = 0x25;  F = 0;  DataSN = 3;  DSL = 12288;  Buffer Offset = 32768			First DataIn PDU of second burst (45056 bytes total so far)		Opcode = 0x25;  F = 0;  DataSN = 4;  DSL = 12288;  Buffer Offset = 45056			Second DataIn PDU of second burst (57344 bytes total so far)		Opcode = 0x25;  F = 1;  DataSN = 5;  DSL = 8192;  Buffer Offset = 57344			Third (last) DataIn PDU of second burst (65536 bytes total so far)		Opcode = 0x25;  F = 0;  DataSN = 6;  DSL = 12288;  Buffer Offset = 65536

⌨️ 快捷键说明

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