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

📄 initiator_tx.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				total_sent += res;			}			sg++;		}		if (unlikely(padding > 0)) {			__u32 pad_bytes = 0;			struct iovec iov = {&pad_bytes, padding};			struct msghdr msg;			memset(&msg, 0, sizeof(msg));			msg.msg_iov = &iov;			msg.msg_iovlen = 1;			oldfs = get_fs();			set_fs(get_ds());			res = sock_sendmsg(sock, &msg, padding);			set_fs(oldfs);			if (res != padding) {				if (res > 0) {					sent = total_sent;					goto finish;				} else {					if (res == -EAGAIN) {						sent = total_sent;						goto eagain;					}					sent = res;					goto finish;				}			}		}		sent = size;	} else {		oldfs = get_fs();		set_fs(get_ds());		sent = sock_sendmsg(current_connection->sock,				    &current_command->tx_msghdr, size);		set_fs(oldfs);	}finish:#else	oldfs = get_fs();	set_fs(get_ds());	sent = sock_sendmsg(current_connection->sock,			    &current_command->tx_msghdr, size);	set_fs(oldfs);#endif	/* now get back exclusive access to this session iscsi structures */	UNH_LOCK(&current_session->sess_lock,current_connection->tx_lock_flags);	TRACE(TRACE_DEBUG, "--sent %d, ITT %u resume\n",	      sent, current_command->init_task_tag);	if (unlikely(sent < size)) {		/* did not send what we expected to send, why? */		if (current_connection->tx_thread == NULL || sent == -EINTR) {			/* thread was killed as part of session shutdown */			retval = -ESRCH;	/* No such process */			goto out;		}		TRACE(TRACE_DEBUG,		      "%s sock_sendmsg returned %d, expected %d\n",		      current->comm, sent, size);		if (sent < 0) {			if (sent != -EAGAIN) {				/* hard error -- report it, then get out */				TRACE_ERROR("%s sock_sendmsg error %d\n",					    current->comm, -sent);				retval = sent;				goto out;			}			sent = 0;	/* got nothing on this send */		}#ifdef K26eagain:#endif		/* need to try again later */		current_command->tx_size -= sent;		current_command->tx_sent_so_far += sent;		current_command->tx_wait_to_send = jiffies + (HZ >> 6);		current_connection->connection_flags |= NEED_TX_WAKEUP;		/* couldn't send all of this command now */		TRACE(TRACE_ISCSI, "%s Part 0x%02x, ITT %u, "		      "%u bytes unsent\n",		      current->comm, opcode,		      current_command->init_task_tag, current_command->tx_size);		/* do nothing more on this command or connection */		current_connection->short_command = current_command;		retval = 0;		goto out;	}	/* sent everything we wanted to send, this pdu is completely sent */	current_connection->short_command = NULL;	if (unlikely(TRACE_TEST(TRACE_DEBUG)					&& opcode == ISCSI_INIT_SCSI_CMND)) {		/* this was a SCSI Request */		TRACE(TRACE_DEBUG, "%s Sent SCSI %s ITT %u "		      "CmndSn %u exp_stat_sn %u length %d\n",		      current->comm,		      printable_scsi_op(current_command->iscsi_cmd.cdb[0],					op_buf),		      ntohl(current_command->iscsi_cmd.init_task_tag),		      ntohl(current_command->iscsi_cmd.cmd_sn),		      ntohl(current_command->iscsi_cmd.exp_stat_sn), size);	}	/* Timestamp the command transmission time - SAI */	current_command->time_stamp = jiffies;	/* Mark that current PDU has been completely sent.  This allows	 * new transfers to be set up in this command's pdu slot.	 */	current_command->tx_sent_so_far += sent;	current_command->tx_size = 0;	if (!(current_command->header_flags & F_BIT)) {		/* F bit is 0, more DataOut PDUs to be sent, keep loop going */		if (atomic_read(&current_connection->tx_sem.count) <= 0) {			up(&current_connection->tx_sem);		}	} else if (opcode == ISCSI_INIT_SCSI_DATA_OUT) {		/* this was the last DataOut PDU in an R2T sequence */		if (!list_empty(&current_connection->r2t_list)) {			/* first DataOut PDU of next R2T ready to be sent */			if (atomic_read(&current_connection->tx_sem.count)<=0) {				up(&current_connection->tx_sem);			}		}	} else if (opcode == ISCSI_INIT_NOP_OUT) {		/* this was the last (only) NopOut PDU sent */		if (current_command->init_task_tag == ALL_ONES) {			/* this was a ping response to target's NopIn			 * Free up the command itself since we will			 * get no further response from target.			 */			current_command->cmd_state					|= CMD_STATE_TXDONE | CMD_STATE_RXDONE;		}	} else if (opcode == ISCSI_INIT_SNACK) {		/* Free SNACK Request from pending commands list - SAI */		current_command->cmd_state					|= CMD_STATE_TXDONE | CMD_STATE_RXDONE;	}#ifdef ISCSI_STATS	UPDATE_TX_SESS_STATS(opcode, current_command,				current_session->sess_stats,				current_connection);#endifout:	return retval;}/* * executed only by tx thread. * when called, NO LOCKS SHOULD BE LOCKED! * Called only once by iscsi_initiator_tx_thread() to shutdown the tx thread, */static voidtx_shutdown_thread(struct connection *conn, struct session *sess){	TRACE(TRACE_DEBUG, "%s shutting down\n", current->comm);	/* get exclusive access to this session iscsi structures */	UNH_LOCK(&sess->sess_lock, conn->tx_lock_flags);	/* do not allow tx_timer to restart itself */	conn->connection_flags |= TX_TIMER_OFF;	if (conn->tx_thread != NULL) {		/* no other thread is already shutting this session down		 * indicate that this thread is shutting itself down		 */		conn->tx_thread = NULL;	}	/* tell anyone waiting that this tx thread is finished */	up(&conn->tx_done_sem);	/* finally, release our exclusive access to the iscsi structures */	UNH_UNLOCK(&sess->sess_lock, conn->tx_lock_flags);	printk("%s Exiting pid %d conn %p\n", current->comm, current->pid,	       conn);}/**************************************************************************** * The tx thread is woken up anytime someone has something * that needs to be sent.  each time it is woken up it searches through the * command table for stuff that it needs to send. * There is only one tx thread for each session. ******************************************************************************/voidiscsi_initiator_tx_thread(void *arg){	struct connection *conn;	struct session *sess;	struct command *command;	int delta;	__u32 nop_timer_expired;	struct list_head *lptr, *next;	conn = (struct connection *) arg;	sess = conn->my_session;	/* Lock kernel to daemonize thread and update tx thread pointer */	lock_kernel();	/* NOTE: struct task_struct has declared char comm[16] *//* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	daemonize(#else	daemonize();	snprintf(current->comm, sizeof(current->comm),#endif		 "tx-%u-%02u", sess->scsi_target_id, conn->connection_id);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 18)	/*	 * Arne Redlich, agr1@users.sourceforge.net:	 * This prevents the tx_thread from becoming a zombie after it exits.	 */	reparent_to_init();#endif	siginitsetinv(&current->blocked, ISCSI_SHUTDOWN_SIGBITS);	/* mark that this tx thread is alive */	conn->tx_thread = current;	unlock_kernel();	printk("%s Starting pid %d conn %p\n", current->comm, current->pid,	       conn);	/* set up counter so NopOut pings can be sent to target periodically */	conn->nop_remaining = sess->nop_period;	TRACE(TRACE_TIMERS, "%s nop_remaining %u\n", current->comm,	      conn->nop_remaining);	/* Always start the tx timer now */	restart_tx_timer(conn);	/* signal anyone waiting that the tx thread is up and running */	up(&conn->tx_done_sem);	for (;;) {		TRACE(TRACE_SEM, "%s blocked on tx_sem\n", current->comm);		if (unlikely(down_interruptible(&conn->tx_sem) < 0)) {			/* did not get the sem but got signalled */			TRACE(TRACE_ISCSI, "%s Killed by signal\n",			      current->comm);			goto leave;		}		TRACE(TRACE_SEM, "%s unblocked on tx_sem\n", current->comm);		/* now get exclusive access to the iscsi structures */		UNH_LOCK(&sess->sess_lock, conn->tx_lock_flags);		/* tx thread just awakened, so no further wakeups needed yet */		conn->connection_flags &= ~NEED_TX_WAKEUP;		/* Free Unused Connections - SAI */		/* clear_free_conn(sess); */		nop_timer_expired = 0;		if (unlikely(atomic_read(&conn->tx_timer_went_off))) {			/* periodic tx timer went off */			TRACE(TRACE_TIMERS, "%s tx_timer_went_off %u, "				"nop_remaining %u\n",				current->comm,				atomic_read(&conn->tx_timer_went_off),				conn->nop_remaining);			atomic_dec(&conn->tx_timer_went_off);			if (conn->nop_remaining) {				/* sending periodic nop pings is enabled */				conn->nop_remaining--;				if (conn->nop_remaining == 0) {					/* time to send a periodic nop					 * on inactive connections					 */					nop_timer_expired = 1;					conn->nop_remaining = sess->nop_period;				}			}		}		/* tx thread IS dependent on rx thread */		if (unlikely(conn->rx_thread == NULL)) {			/* no rx thread, connection not up yet			 * or was brought down unexpectedly.			 * In either case, don't try to use it!			 */			printk("%s exiting, no rx thread!\n", current->comm);			goto out;		}		/* See if this connection got logged out */		if (unlikely(conn->connection_state == CONNECTION_LOGGED_OUT)) {			printk("%s logged out\n", current->comm);			goto out;		}		/* if timer went off and this connection has had no		 * activity since the last timer then send a		 * NopOut ping to the target		 */		if (unlikely(nop_timer_expired			&& list_empty(&conn->pending_commands))) {			/* timer went off and nothing pending			 * on this connection			 */			if (!(conn->connection_flags & GOT_ACTIVITY)) {				/* no activity since				 * last timer timed out,				 * send nop ping				 */				drive_nopout(conn, sess, 0, 1);			} else {				/* had activity, turn off				 * the flag to start next period				 */				conn->connection_flags &= ~GOT_ACTIVITY;			}		}		list_for_each_safe(lptr, next, &conn->pending_commands) {			command = list_entry(lptr,struct command,link);			/* bypass this command if target window closed to it */			if (beyond_window(sess, conn, command))				continue;			if ( command->need_write_built) {				/* A write request.				 * Need to construct the infrastructure 				 */				TRACE(TRACE_DEBUG,				      "command %p marked for write\n",				      command);				build_write_command(sess, conn, command);				command->need_write_built = 0 ; 			}			if (unlikely(TRACE_TEST(TRACE_DEBUG))) {				delta = jiffies - command->time_stamp;				TRACE(TRACE_DEBUG,				      "%s for command %p, tx_size %u, "				      "ITT %u, time_stamp %u, "				      "delta %d\n",				      current->comm, command,				      command->tx_size,				      command->init_task_tag,				      command->time_stamp,				      delta);			}			if (unlikely(conn->short_command != NULL)) {				if (conn->short_command != command) {					/* when we have a partial send				 	* outstanding, don't look at any other				 	* command until that is resumed				 	*/					break;				}			}			if (unlikely(conn->sock == NULL))				goto out;			/* Check if command re-transmission required			 * -- SAI			 */			if (unlikely(!command->tx_size			      && !check_for_retransmit(sess, conn, command))) {				/* nothing works on rexmit, shut				 * this tx thread down				 */				printk("%s exiting, bad retransmit, ITT %u\n",				       current->comm,				       command->init_task_tag);				goto out;			}			if ((delta = ready_to_xmit(sess, conn, command)) <= 0) {				if (delta < 0) {					/* do nothing more on					 * this command or connection					 */					break;				}				/* this command not ready to send */				continue;			}			/* have a command that needs to be			 * sent on this connection			 * and target window is open			 * enough to receive it			 */			delta = do_tx_send(sess, conn, command);			if (unlikely(delta <= 0)) {				if (delta == 0) {					/* do nothing more on					 * this command or connection					 */					break;				}				/* fatal error */				printk("%s exiting due to error %d\n",				       current->comm, -delta);				goto out;			}			/* in case this changed while we gave			 * up the lock			 */			next = lptr->next;			if (command->still_to_send == 0)				command->cmd_state |= CMD_STATE_TXDONE;			free_pending_command(command, conn);		} /* end of for command loop */		/* Check if a Connection Recovery Test needs		 * to be done - SAI		 */		if (unlikely(conn->rec_tests == 8)) {			if (sess->nconnections <= 1) {				UNH_UNLOCK(&sess->sess_lock,					   conn->tx_lock_flags);				create_rec_conn(sess->connection_head);				UNH_LOCK(&sess->sess_lock,					 conn->tx_lock_flags);			}			drive_logout(sess, conn, sess->oper_param->				     ErrorRecoveryLevel);			conn->rec_tests = 0;		}		/* release our exclusive access to the session		 * iscsi structures and resume infinite loop		 */		UNH_UNLOCK(&sess->sess_lock, conn->tx_lock_flags);	} /* end of infinite loop */	/* NOT REACHED */out:	/* release our exclusive access to the iscsi session structures */	UNH_UNLOCK(&sess->sess_lock, conn->tx_lock_flags);leave:	tx_shutdown_thread(conn, sess);}

⌨️ 快捷键说明

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