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

📄 iscsi_initiator.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * already zeroed out the entire PDU header in setup_command() above,	 * we don't need to do anything else here in this case.	 */	if (lun) {		pack_lun(lun,			 conn->connection_flags & USE_FLAT_SPACE_LUN,			 (__u8 *)&iscsi_cmd->lun);	}	iscsi_cmd->xfer_len = htonl(Cmnd->request_bufflen);	TRACE(TRACE_DEBUG, "Xfer len for queuecommand %d\n",	      Cmnd->request_bufflen);	/* copy the SCSI CDB into the PDU */	memcpy(iscsi_cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);	if (Cmnd->sc_data_direction == SCSI_DATA_WRITE) {		/* SCSI Command has write data to be sent.		 * Mark the cmd to be built when xmit_thread wakes up in order		 * to avoid any potential sleep hazards in		 * build_write_command(), since we may be in an interrupt		 * context here.		 */ 		new_command->need_write_built |= CMD_NEEDS_WRITE_BUILT;		TRACE(TRACE_DEBUG, "command %p marked for write\n",			new_command);	} else {		/* not a write, probably a read, but check out of curiousity */		/* always set the F_BIT if it is not a WRITE SCSI Commamnd */		if (likely(Cmnd->sc_data_direction == SCSI_DATA_READ)) {			iscsi_cmd->flags = F_BIT | R_BIT;		} else {			/* direction given as neither Read nor Write */			TRACE(TRACE_DEBUG,			      "sc_data_direction %u not READ or WRITE\n",			      Cmnd->sc_data_direction);			if (unlikely(Cmnd->request_bufflen != 0)) {				TRACE_ERROR("request_bufflen %u not zero when "					    "sc_data_direction %u not READ or "					    "WRITE\n",					    Cmnd->request_bufflen,					    Cmnd->sc_data_direction);				iscsi_cmd->flags = F_BIT | R_BIT;			} else {				/* no data expected to be transfered,				 * not READ or WRITE, so only set the F bit				 */				iscsi_cmd->flags = F_BIT;			}		}	}	/* attach the new SCSI Request command to end of pending commands list	 * this also sets the ITT and the CmdSN.	 */	attach_pending_command(new_command, conn, 1);out:	TRACE(TRACE_ENTER_LEAVE, "Leave scsi_to_iscsi, retval %d\n", retval);	return retval;}/***************************************************************************** This function is called by the system when the abort_timer set in* the iscsi_initiator_abort function expires. This function wakes up* the thread/process which is waiting on the task_mgt_sem semaphore.****************************************************************************/static voidabort_timer_function(unsigned long data){	TRACE(TRACE_ENTER_LEAVE, "Enter abort_timer_function\n");	up((struct semaphore *) data);	TRACE(TRACE_ENTER_LEAVE, "Leave abort_timer_function\n");}static voiddump_command_info(struct command *related_command,		  struct connection *related_connection,		  struct session *related_session){	int delta_t;	struct r2t_cookie *cookie;	delta_t = jiffies - related_command->time_stamp;	printk	    (" SCpnt %p, op 0x%02x, flags 0x%02x, time_stamp %u, delta_t %d\n",	     related_command->SCpnt, related_command->header_opcode,	     related_command->header_flags, related_command->time_stamp,	     delta_t);	printk(" recvd_length %u, data_offset %u, still_to_send %u, "	       "wait_to_send %u, cmd_state 0x%02x\n",	       related_command->recvd_length,	       related_command->data_offset, related_command->still_to_send,	       related_command->tx_wait_to_send, related_command->cmd_state);	if (related_command->SCpnt) {		printk( " request_bufflen %u, recv_so_far %u, "			"data_in_sn %u, direction %c\n",			related_command->SCpnt->request_bufflen,			related_command->r2t_range_list.limit,			related_command->data_in_sn,			related_command->SCpnt->sc_data_direction				== SCSI_DATA_WRITE ? 'W' : 'R');	}	printk(" tx_size %u, tx_sent_so_far %u, r2t_sn %u, n_r2t_cookies %u, "	       "msg_flags 0x%08x\n",	       related_command->tx_size, related_command->tx_sent_so_far,	       related_command->r2t_sn, related_command->n_r2t_cookies,	       related_command->cmd_msg_flags);	delta_t = related_session->max_cmd_sn				- ntohl(related_command->iscsi_cmd.cmd_sn);	printk(" short_command %p, max_cmd_sn %u, cmd_sn %u, delta %d\n",	       related_connection->short_command, related_session->max_cmd_sn,	       ntohl(related_command->iscsi_cmd.cmd_sn), delta_t);	if (list_empty(&related_command->r2t_cookies)) {		printk(" No R2T cookies\n");	} else {		list_for_each_entry(cookie,&related_command->r2t_cookies,link) {			printk			    ("cookie TTT %u, data_out_sn %u, r2t_xfer_length "			     "%d, offset %u\n", ntohl(cookie->target_xfer_tag),			     cookie->data_out_sn, (int) cookie->r2t_xfer_length,			     cookie->offset);		}	}}/* * when called, NO LOCKS SHOULD BE LOCKED! * Searches iscsi structures for Cmnd * Returns 1 on success, 0 on failure to find this command * On success, it has filled in the last 3 parameters : *	session, connection, and related command *	with session->sess_lock LOCKED. * On failure, these last 3 parameters are unchanged /undefined * and session->sess_lock is NOT LOCKED. */static intfind_aborted_command(struct scsi_cmnd * Cmnd,		     struct session **found_session,		     struct connection **found_connection,		     struct command **found_command,		     int print_on_success,		     unsigned long *lock_flags){	struct session *related_session;	struct connection *related_connection = NULL;	struct command *related_command;	struct iscsi_hostdata *hostdata;	int retval = 0;		/* assume failure */	__u32 target_id;	unsigned long flags;	UNH_LOCK(&host_data_lock, flags);/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	target_id = Cmnd->device->id;	hostdata = (struct iscsi_hostdata *) Cmnd->device->host->hostdata;#else	target_id = Cmnd->target;	hostdata = (struct iscsi_hostdata *) Cmnd->host->hostdata;#endif	if (unlikely(hostdata != global_hostdata)) {		TRACE_ERROR		    ("Hostdata struct %p not same as global_hostdata %p\n",		     hostdata, global_hostdata);		UNH_UNLOCK(&host_data_lock, flags);		goto out;	}	/* Find out the session that corresponds to this target ID */	related_session = find_session_by_id(target_id, hostdata);	if (unlikely(related_session == NULL)) {		TRACE_ERROR("No session for target %u\n", target_id);		UNH_UNLOCK(&host_data_lock, flags);		goto out;	}	UNH_LOCK(&related_session->sess_lock, *lock_flags);	UNH_UNLOCK(&host_data_lock, flags);	/* check if the session is in full feature phase or not */	if (unlikely(	    related_session->session_state != SESSION_FULL_FEATURE_PHASE	    || (related_connection = related_session->connection_head) == NULL	    || related_connection->rx_thread == NULL	    || related_connection->tx_thread == NULL	    || related_connection->connection_state	    	!= CONNECTION_FULL_FEATURE_PHASE)) {		TRACE_ERROR("No connection to target %u\n", target_id);		UNH_UNLOCK(&related_session->sess_lock, *lock_flags);		goto out;	}	/* search for the PDU containing the SCSI command	 * which has to be aborted	 */	for (; related_connection;	     related_connection = related_connection->next) {		list_for_each_entry(related_command,				    &related_connection->pending_commands,				    link) {			if (related_command->SCpnt == Cmnd) {				if (likely((related_command->iscsi_cmd.						opcode & ISCSI_OPCODE)							==ISCSI_INIT_SCSI_CMND))					goto found_command_match;				TRACE_ERROR				    ("Related Cmnd %p for target %u has "				     "opcode 0x%02x, expected 0x%02x\n", Cmnd,				     target_id,				     related_command->iscsi_cmd.opcode							& ISCSI_OPCODE,				     ISCSI_INIT_SCSI_CMND);				UNH_UNLOCK(&related_session->sess_lock,					   *lock_flags);				goto out;			}		}	}	/* did not find the command to abort, dump pending cmnds */	TRACE_ERROR("No related SCSI Cmnd %p for target %u\n", Cmnd,		    target_id);	for (related_connection = related_session->connection_head;	     related_connection != NULL;	     related_connection = related_connection->next) {		printk		    ("   pending cmds for connection %p, CID %u, jiffies %lu\n",		     related_connection, related_connection->connection_id,		     jiffies);		list_for_each_entry(related_command,				    &related_connection->pending_commands,				    link) {			dump_command_info(related_command, related_connection,					  related_session);		}	}	UNH_UNLOCK(&related_session->sess_lock, *lock_flags);	goto out;found_command_match:	/* successfully found the matching command to be aborted	 * session->sess_lock is LOCKED	 */	if (print_on_success) {		TRACE_ERROR("Aborting SCSI Cmnd with ITT %u, CmndSN %u, "			"jiffies %lu\n",		    	related_command->init_task_tag,			ntohl(related_command->iscsi_cmd.cmd_sn),			jiffies);		dump_command_info(related_command, related_connection,				  related_session);	}	*found_session = related_session;	*found_connection = related_connection;	*found_command = related_command;	retval = 1;out:	return retval;}/* * the session->sess_lock MUST be held by the calling process/thread. * Allocates, sets up, and sends a task management pdu to target, * then waits (up to a time limit) for a response from the target, * and finally frees the task management command structure. * Returns NULL in value of related_command on any error. */static voidtm_send_and_wait(struct scsi_cmnd * Cmnd,		 struct session *related_session,		 struct connection *conn,		 struct command **related_command,		 unsigned long *lock_flags){	struct timer_list abort_timer;	struct command *task_mgt_command;	struct iscsi_init_task_mgt_command *task_mgt_command_hdr;	__u32 related_itt, lun;	task_mgt_command = setup_command(NULL, conn);	if (unlikely(task_mgt_command == NULL)) {		*related_command = NULL;		goto out;	}	related_itt = (*related_command)->init_task_tag;	task_mgt_command->task_mgt_function = TMF_ABORT_TASK;	task_mgt_command->task_mgt_response = FUNCTION_REJECTED;	/* fill up the task_mgt_header info. -- command should be immediate */	task_mgt_command_hdr = (struct iscsi_init_task_mgt_command *)	    &task_mgt_command->iscsi_cmd;	task_mgt_command_hdr->opcode = (ISCSI_INIT_TASK_MGMT_CMND | I_BIT);	task_mgt_command_hdr->function = (TMF_ABORT_TASK | F_BIT);/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	lun = Cmnd->device->lun;#else	lun = Cmnd->lun;#endif	/* SAM-2, section 4.12.2 LUN 0 address	 * "To address the LUN 0 of a SCSI device the peripheral device	 * address method shall be used."	 *	 * What this means is that whenever the LUN is 0, the full 8 bytes of	 * the LUN field in the iscsi PDU will also be 0. Because we have	 * already zeroed out the entire PDU header in setup_command() above,	 * we don't need to do anything else here in this case.	 */	if (lun) {		pack_lun(lun,			 conn->connection_flags & USE_FLAT_SPACE_LUN,			 (__u8 *)&task_mgt_command_hdr->lun);	}	task_mgt_command_hdr->ref_task_tag = htonl(related_itt);	task_mgt_command_hdr->ref_cmd_sn = (*related_command)->iscsi_cmd.cmd_sn;	/* attach the new task mgt command to end of pending commands list	 * this also assigns the ITT and sets the CmdSN.	 */	attach_pending_command(task_mgt_command, conn, 1);	TRACE(TRACE_DEBUG, "Waiting to get task mgt. rsp from the target\n");	/* set up timer and wait on task_mgt_sem until the timer expires */	/* or we receive the task management response from the target */	init_timer(&abort_timer);	abort_timer.expires = jiffies + ABORT_TIMEOUT;	abort_timer.data = (__u32) &conn->task_mgt_sem;	abort_timer.function = abort_timer_function;	add_timer(&abort_timer);	/* release our exclusive access to the iscsi structures while waiting */	UNH_UNLOCK(&related_session->sess_lock, *lock_flags);	/* wait for our timer to expire */	down(&conn->task_mgt_sem);	del_timer_sync(&abort_timer);	TRACE(TRACE_DEBUG, "Awake after down on task mgt. sem\n");	TRACE(TRACE_DEBUG, "Task mgt response 0x%02x\n",	      task_mgt_command->task_mgt_response);	/*  we have to do all this all over again because we may have been	   "away" for a long time and our operating environment could have	   changed during that interval -- the session and/or connection	   could have been closed (unlikely) or the command could have	   completed  and been removed from the pending commands list	   (more likely).	 */	if (!find_aborted_command(Cmnd, &related_session,			&conn, related_command, 0, lock_flags)) {		/* command must have "disappeared" while we were away! */		/* get lock so we can free the tm command structure */		UNH_LOCK(&related_session->sess_lock, *lock_flags);		*related_command = NULL;	} else {		/* Successfully found matching command (again) to be aborted.	 	 * Corresponding session, connection and command are valid.	 	 * Session lock is held. ITT must be same as it was before.	 	 */		if (unlikely((*related_command)->init_task_tag != related_itt)){			/* command changed while we were away! */			TRACE_ERROR("Aborted command ITT now %u, used to be %u\n",				    (*related_command)->init_task_tag,				    related_itt);			*related_command = NULL;		}	}	/* free the task_mgt_command structure */	task_mgt_command->cmd_state |= CMD_STATE_RXDONE | CMD_STATE_TXDONE;	free_pending_command(task_mgt_command, conn);out:	return;}/*************************************************************************** * when called, NO LOCKS SHOULD BE LOCKED! * This function is called by the SCSI Mid-level when it has to abort any * SCSI Command. This function will check if the command has been sent to the * target for satisfying the request. If it has been sent, then this function * will set up TCP buffers to send out a Task Mgt. Command. * When called by the SCSI Mid-level (from linux/drivers/scsi/scsi_error.c) * the io_request_lock (or equivalent) is held by the caller. * ****************************************************************************/static intiscsi_initiator_abort(struct scsi_cmnd * Cmnd){	unsigned long lock_flags;	/* pessimistic assumption */	int retval = FAILED;	struct session *related_session;	struct connection *related_connection;	struct command *related_command;#if defined(CONFIG_ISCSI_DEBUG)	__u32 save_trace;#endif

⌨️ 快捷键说明

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