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

📄 initiator_utilities.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	__u32 lun;	slength = related_command->SCpnt->request_bufflen;	TRACE(TRACE_DEBUG, "completed read capacity, slength %d, missing %d\n",		slength, missing);	if (missing > 0)		slength -= missing;	if (slength >= 8) {#ifdef K26		lun = related_command->SCpnt->device->lun;#else		lun = related_command->SCpnt->lun;#endif		sess->capacity_lba[lun] = ntohl(			*(__u32 *)related_command->SCpnt->request_buffer);		sess->capacity_len[lun] = ntohl(			*(__u32 *)(related_command->SCpnt->request_buffer + 4));		printk("capacity for lun %u [%u, %u]\n", lun,			sess->capacity_lba[lun],			sess->capacity_len[lun]);	}}/* we just successfully completed a read block limits command */voidsave_limits(struct session *sess, struct command *related_command, int missing){	int slength;	__u32 lun;	slength = related_command->SCpnt->request_bufflen;	TRACE(TRACE_DEBUG, "completed read block limits, slength %d, "		"missing %d\n", slength, missing);	if (missing > 0)		slength -= missing;	if (slength >= 6) {#ifdef K26		lun = related_command->SCpnt->device->lun;#else		lun = related_command->SCpnt->lun;#endif		sess->limit_max[lun] = ntohl(			(*(__u32 *)related_command->SCpnt->request_buffer))			& MASK_24_BITS;		sess->limit_min[lun] = ntohs(		       (*(__u16 *)(related_command->SCpnt->request_buffer + 4)))		       & MASK_24_BITS;		printk("block limits for lun %u [%u, %u]\n", lun,			sess->limit_min[lun],			sess->limit_max[lun]);	}}intsend_data_ack_snack(struct connection *current_connection,		    struct command *related_command, __u32 increment){	int retval = 1;	struct init_error_rec err_rec;	struct iscsi_targ_scsi_data_in *header;	/* time to send a snack because of previous error */	TRACE(TRACE_ISCSI,	     "Sending SNACK type %u, ITT %u, offset %u, begrun %u, "	     "runlen %u\n", DATA_R2T_SNACK,	     related_command->init_task_tag,	     related_command->cmd_error_offset,	     related_command->cmd_error_begrun,	     related_command->cmd_error_runlen);	related_command->cmd_error_state = CMD_USING_SNACK;	/* save fields from current command so they can be restored after	 * retransmission (only when current command is DataIn with A bit set)	 */	if (increment == 0) {		/* cause by a DataIn with A bit set, save stuff */		related_command->abit_offset = related_command->data_offset;		related_command->abit_in_sn = related_command->data_in_sn;		header = (struct iscsi_targ_scsi_data_in *)						current_connection->rx_buf;		related_command->abit_ttt = header->target_xfer_tag;		related_command->abit_lun = header->lun;	}	/* reset "normal" fields in current command to handle retransmission */	related_command->data_offset = related_command->cmd_error_offset;	related_command->data_in_sn = related_command->cmd_error_begrun;	/* MAYBE undo previous increment of StatSN as we do not want to	 * acknowledge correct receipt of all the DataIns yet.	 * Save the increment so we can apply it again when all DataIns are ok	 */	current_connection->exp_stat_sn -= increment;	current_connection->increment = increment;	err_rec.curr_conn = current_connection;	err_rec.related_cmd = related_command;	err_rec.err_type = SEQUENCE_ERR;	if (!init_send_snack(&err_rec, related_command->cmd_error_begrun,			   related_command->cmd_error_runlen, DATA_R2T_SNACK)) {		/* SNACK not sent for some reason, escalate to session recovry*/		retval = init_session_recovery(&err_rec);	}	return retval;}/* * executed only by rx thread. * process the common parts of a SCSIResponse PDU and a DataIn * PDU with the S-bit set ("phase collapse") * the current_session->sess_lock MUST be held by the calling thread. * Returns >0 on success, session lock is locked *	   =0 on failure, session lock is locked *	   <0 on failure, session lock is NOT locked */intdo_scsi_response(struct connection *current_connection,		 struct command *related_command,		 struct iscsi_targ_scsi_rsp *header,		 int received,		 __u8 * buffer){	int missing, slength, retval = 1;	__u32 residual;	TRACE(TRACE_ENTER_LEAVE, "Enter do_scsi_response\n");	if (unlikely(related_command->cmd_error_state == CMD_NEEDS_SNACK)) {		/* time to send a snack because of previous error */		retval = send_data_ack_snack(current_connection,					     related_command, 1);		goto out;	}	residual = ntohl(header->resid);	/* see if initiator and target agree on amount of data transfered */	if (unlikely(related_command->r2t_range_list.next != NULL)) {		/* Command with DataSequenceInOrder==No */		/* expected range of any command is: offset=0, limit=bufflen */		related_command->r2t_range_list.offset = 0;		related_command->r2t_range_list.limit		    = related_command->SCpnt->request_bufflen;		missing =		    check_range_list_complete(&related_command->r2t_range_list);	} else {		/* Command with DataSequenceInOrder==Yes */		missing = related_command->SCpnt->request_bufflen				- related_command->data_offset;	}	if (unlikely(header->flags & U_BIT)) {		/* U bit is set, indicating underflow, check residual count */		TRACE(TRACE_ISCSI, "Underflow: Residual count %u\n", residual);		if (missing != residual && !(header->status & STATUS_MASK)) {			TRACE_ERROR("Underflow Residual count %u doesn't match "				    "expected %d\n", residual, missing);		}	} else if (unlikely(header->flags & O_BIT)) {		/* O bit is set, indicating overflow, check residual count */		TRACE(TRACE_ISCSI, "Overflow: Residual count %u\n", residual);		if (!(header->status & STATUS_MASK)) {				if (missing != 0) {				TRACE_ERROR			    	("Overflow bit set, but still missing %d "				"bytes\n", missing);			} else if (residual == 0) {				TRACE_ERROR			    	("Overflow bit set, but Residual count is 0\n");			}		}	} else if (unlikely(residual != 0)) {		TRACE_ERROR		    ("Neither Overflow nor Underflow set, but Residual count is"		     " %u\n", residual);	}	/* pass the final status back up to the SCSI Mid-level	 * the "result" field of the command contains 4 independent bytes:	 * byte 0: status byte returned from the device itself in bits 1 thru 5	 * byte 1: status returned from the host adapter (always 0 for us)	 * byte 2: status returned by the low-level driver	 * byte 3: "simply the message byte that comes back" whatever that is.	 *	 * The byte 2 errors are defined in /usr/src/linux/drivers/scsi/scsi.h	 * and are symbols of the form DID_xxx.  DID_OK is conveniently 0.	 */	related_command->SCpnt->result = header->status;	if (unlikely(header->status & STATUS_MASK)) {		TRACE_ERROR("%s scsi response error from target, "			    "status 0x%02x\n",			    current->comm, header->status);		/* mark this as an internal error of some sort */		related_command->SCpnt->result |= (DID_ERROR << 16);		/* we will never transmit anything else for this command */		related_command->cmd_state |= CMD_STATE_TXDONE;		/* Linux defines CHECK_CONDITION as 0x01,		 * and SAM-2 requires it to be 0x02 (see Draft 20,		 * Section 10.4.2).  This is because Linux does not		 * consider the low order bit to be part of the status,		 * since SAM-2 requires that bit to be 0.		 * The status_byte() macro in linux/drivers/scsi/scsi.h		 * handles this.  See also linux/include/scsi/scsi.h.		 */		if (likely(status_byte(header->status) == CHECK_CONDITION)) {			/* Draft 20, Section 10.4.7 Data Segment -			 * Sense and Response Data Segment "iSCSI			 * targets MUST support and enable autosense.			 * If Status is CHECK CONDITION (0x02),			 * then the Data Segment MUST contain sense			 * data for the failed command."			 */			slength = 0;			if (received <= 0 || buffer == NULL) {				TRACE_ERROR				    ("CHECK CONDITION but no sense data\n");			} else {				if (received < 2) {					TRACE_ERROR("%d data bytes not enough "						    "to contain sense length\n",						    received);				} else {					/* big-endian 16-bits */					slength = (buffer[0] << 8) + buffer[1];					if (slength > received - 2) {						TRACE_ERROR("%d sense data "						"bytes but only %d actually "						"received\n", slength,						received - 2);						slength = received - 2;					}					if (slength > SCSI_SENSE_BUFFERSIZE) {						if (TRACE_TEST(TRACE_ISCSI)) {						      TRACE_WARNING("received "						      "%d sense data bytes but "						      "midlevel buffer holds "						      "%d\n",						      slength,						      SCSI_SENSE_BUFFERSIZE);						}						slength = SCSI_SENSE_BUFFERSIZE;					}					if (slength > 0) {						/* have some sense data,						 * copy it into buffer						 */						memcpy(related_command->SCpnt->						       sense_buffer, &buffer[2],						       slength);						/* Note -- we expect the						 * midlevel to have zeroed the						 * sense buffer before calling						 * queuecommand().  Therefore,						 * we do not have to zero the						 * unfilled part of the buf						 * (and do not have to do						 * anything if sense data is						 * missing completely).						 */						/* mark that driver sense						 * data is present						 */						related_command->SCpnt-> result							|= (DRIVER_SENSE << 24);						/* print the sense data */						printk("%d bytes of sense "						       "data\n", slength);						dump_buffer(buffer + 2,							    slength);					}				}			}		}	} else if (related_command->header_opcode == ISCSI_INIT_SCSI_CMND			&& related_command->SCpnt != NULL			&& related_command->SCpnt->use_sg == 0) {		if (related_command->iscsi_cmd.cdb[0] == INQUIRY)			save_inquiry(current_connection->my_session,					related_command, missing);		else if (related_command->iscsi_cmd.cdb[0] == READ_CAPACITY)			save_capacity(current_connection->my_session,					related_command, missing);		else if (related_command->iscsi_cmd.cdb[0] == READ_BLOCK_LIMITS)			save_limits(current_connection->my_session,					related_command, missing);	}	/* no errors on this command or done with recovery */	related_command->cmd_state |= CMD_STATE_RXDONE;	free_pending_command(related_command, current_connection);out:	TRACE(TRACE_ENTER_LEAVE, "Leave do_scsi_response, retval %d\n", retval);	return retval;}/* * executed by init_recovery thread, scsi midlevel process. * the session->sess_lock MUST be held by the calling process/thread. * Called to allocate space for a struct command and then initialize it. * Returns pointer to newly allocated and initialized command if all ok, * else NULL. */struct command *setup_command(struct scsi_cmnd * Cmnd, struct connection *conn){	struct command *new_command;	struct session *sess = conn->my_session;	struct list_head *lptr;	TRACE(TRACE_ENTER_LEAVE, "Enter setup_command\n");	if (unlikely(list_empty(&sess->free_commands))) {		TRACE_WARNING("setup_command allocating %d bytes for "			      "%uth command in session\n",			      sizeof(struct command),			      sess->n_commands_alloced+1);		new_command = (struct command *)				my_kmalloc(sizeof(struct command), "command");		if (unlikely(new_command == NULL))			goto out;		sess->n_commands_alloced++;	} else {		lptr = sess->free_commands.next;		list_del(lptr);		new_command = list_entry(lptr, struct command, link);	}	/* setup the new command struct (most fields 0/NULL)	 *	 * Draft 20, Section 10.7.5 DataSN "For input (read) or	 * bidirectional Data-In PDUs, the DataSN is the	 * input PDU number within the data transfer for the	 * command identified by the Initiator Task Tag."	 *	 * Draft 20, Section 10.8.2 R2TSN	 * "R2TSN is the R2T PDU input PDU number within	 * the command identified by the Initiator Task Tag."	 */	/* zero out just the first part of the struct command */	memset(new_command, 0, (long)&((struct command *)NULL)->SCpnt);	new_command->SCpnt = Cmnd;	INIT_LIST_HEAD(&new_command->r2t_cookies);	/* set up the transmit i/o vector for the iscsi header */	setup_header_iovec(conn, new_command);#ifdef K26	new_command->pindex = 0;	new_command->padding = 0;#endifout:	TRACE(TRACE_ENTER_LEAVE, "Leave setup_command, command %p\n",	      new_command);	return new_command;}/* * executed only by rx thread. * called only from recv_data_in_data() * There is a Data Digest err, handle appropriately - SAI */static int __attribute__ ((no_instrument_function))recv_data_in_error (struct connection *current_connection,		    struct command *related_command,		    struct iscsi_targ_scsi_data_in *data_in_header,		    __u32 *size){	int received;	struct init_error_rec err_rec;#ifdef ISCSI_STATS	current_connection->my_session->sess_stats->iscsi_ssn_digest_err++;#endif	err_rec.curr_conn = current_connection;	err_rec.related_cmd = related_command;	err_rec.err_type = PAYLOAD_DIGERR;	received = init_do_error_recovery(&err_rec);	if (unlikely(received <= 0))		goto out;	/* force the expected data offset to the one received in order 	 * to avoid a cascade of error messages 	 */	if (likely(related_command != NULL)) {		related_command->data_offset += *size;		TRACE(TRACE_DEBUG, "Bump offset by %d, received %d\n", *size,			received);		/* do not count this data as having been received yet */		*size = 0;	}out:	return received;

⌨️ 快捷键说明

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