Beispiel #1
0
static void
target_stat(char **msg, char *targ_name, mgmt_type_t type)
{
	iscsi_conn_t	*c;
	msg_t		*m;
	target_queue_t	*q = queue_alloc();
	mgmt_request_t	mgmt_rqst;
	int		msg_sent,
			i;
	extern pthread_mutex_t	port_mutex;

	mgmt_rqst.m_q		= q;
	mgmt_rqst.m_u.m_resp	= msg;
	mgmt_rqst.m_time	= time(NULL);
	mgmt_rqst.m_request	= type;
	(void) pthread_mutex_init(&mgmt_rqst.m_resp_mutex, NULL);

	(void) pthread_mutex_lock(&port_mutex);
	mgmt_rqst.m_targ_name	= targ_name;
	msg_sent		= 0;
	for (c = conn_head; c; c = c->c_next) {
		if (c->c_state == S5_LOGGED_IN) {
			/*
			 * Only send requests for statistics to
			 * connections that are up. Could even
			 * go further and only look at connections
			 * which are S5_LOGGED_IN, but there may
			 * be statistics, such as connection time,
			 * which we'd like to have.
			 */
			queue_message_set(c->c_dataq, 0, msg_mgmt_rqst,
			    &mgmt_rqst);
			msg_sent++;
		}
	}
	(void) pthread_mutex_unlock(&port_mutex);

	/*
	 * Comment: main.c:list_targets:1
	 * We wait for the responses without the port_mutex
	 * being held. There is a small window between when the
	 * connection last listens for a message and when the
	 * queue is freed. During that time the connection will
	 * attempt to grab the port_mutex lock so that it
	 * can unlink itself and call queueu_free(). If we sent
	 * the message with the lock held and then wait for a response
	 * it's possible that the connection will deadlock waiting
	 * to get the port_mutex.
	 */
	for (i = 0; i < msg_sent; i++) {
		m = queue_message_get(q);
		queue_message_free(m);
	}
	queue_free(q, NULL);
}
Beispiel #2
0
Datei: util.c Projekt: imp/slist
static void
send_named_msg(iscsi_conn_t *c, msg_type_t t, char *name)
{
	target_queue_t	*q = queue_alloc();
	msg_t		*m;
	name_request_t	n;

	n.nr_q		= q;
	n.nr_name	= name;

	queue_message_set(c->c_sessq, 0, t, &n);
	m = queue_message_get(q);
	queue_message_free(m);
	queue_free(q, NULL);
}
Beispiel #3
0
/*
 * []----
 * | sess_process -- handle messages from the connection(s)
 * []----
 */
static void *
sess_process(void *v)
{
	iscsi_sess_t	*s = (iscsi_sess_t *)v;
	iscsi_conn_t	*c;
	iscsi_cmd_t	*cmd;
	msg_t		*m;
	Boolean_t	process = True;
	mgmt_request_t	*mgmt;
	name_request_t	*nr;
	t10_cmd_t	*t10_cmd;
	char		**buf,
			local_buf[16];
	int		lun;
	extern void dataout_callback(t10_cmd_t *t, char *data, size_t *xfer);

	(void) pthread_mutex_lock(&s->s_mutex);
	s->s_state = SS_RUNNING;
	(void) pthread_mutex_unlock(&s->s_mutex);
	do {
		m = queue_message_get(s->s_sessq);
		switch (m->msg_type) {
		case msg_cmd_send:
			cmd = (iscsi_cmd_t *)m->msg_data;
			if (s->s_t10 == NULL) {

				/*
				 * The value of 0x960 comes from T10.
				 * See SPC-4, revision 1a, section 6.4.2,
				 * table 87
				 *
				 * XXX Need to rethink how I should do
				 * the callback.
				 */
				s->s_t10 = t10_handle_create(s->s_t_name,
				    T10_TRANS_ISCSI, s->s_conn_head->c_tpgt,
				    s->s_conn_head->c_max_burst_len,
				    s->s_t10q, dataout_callback);
			}
			if (t10_cmd_create(s->s_t10, cmd->c_lun, cmd->c_scb,
			    cmd->c_scb_len, (transport_t)cmd,
			    &t10_cmd) == False) {

				queue_prt(s->s_mgmtq, Q_SESS_ERRS,
				    "SES%x  FAILED to create cmd", s->s_num);
				/*
				 * If the command create failed, the T10 layer
				 * will attempt to create a sense buffer
				 * telling the initiator what went wrong. If
				 * that layer was unable to accomplish that
				 * things are really bad and we need to just
				 * close the connection.
				 */
				if (cmd->c_t10_cmd != NULL) {
					queue_message_set(
					    cmd->c_allegiance->c_dataq,
					    0, msg_cmd_cmplt, t10_cmd);
				} else
					conn_state(cmd->c_allegiance, T11);
			} else {
				(void) pthread_mutex_lock(
				    &cmd->c_allegiance->c_mutex);
				if (cmd->c_state != CmdCanceled) {
					cmd->c_t10_cmd = t10_cmd;
					(void) t10_cmd_send(s->s_t10,
					    cmd->c_t10_cmd, cmd->c_data,
					    cmd->c_data_len);
				} else {
					t10_cmd_state(t10_cmd,
					    T10_Cmd_Event_Canceled);
				}
				(void) pthread_mutex_unlock(
				    &cmd->c_allegiance->c_mutex);
			}
			break;

		case msg_cmd_data_out:
			cmd = (iscsi_cmd_t *)m->msg_data;
			if (s->s_t10 != NULL)
				(void) t10_cmd_data(s->s_t10, cmd->c_t10_cmd,
				    cmd->c_offset_out, cmd->c_data,
				    cmd->c_data_len);
			break;

		case msg_targ_inventory_change:
			if (s->s_t10 != NULL)
				(void) t10_task_mgmt(s->s_t10, InventoryChange,
				    0, 0);
			break;

		case msg_lu_capacity_change:
			lun = (int)(uintptr_t)m->msg_data;
			if (s->s_t10 != NULL)
				(void) t10_task_mgmt(s->s_t10, CapacityChange,
				    lun, 0);
			break;

		case msg_reset_targ:
			if (s->s_t10 != NULL)
				(void) t10_task_mgmt(s->s_t10, ResetTarget,
				    0, 0);
			break;

		case msg_reset_lu:
			if (s->s_t10 != NULL)
				(void) t10_task_mgmt(s->s_t10, ResetLun,
				    (int)(uintptr_t)m->msg_data, 0);
			break;

		case msg_shutdown:
			(void) pthread_mutex_lock(&s->s_mutex);
			s->s_state = SS_SHUTDOWN_START;
			(void) pthread_mutex_unlock(&s->s_mutex);

			/*
			 * Shutdown rquest comming from a connection. Only
			 * shutdown the STE if this is the last connection
			 * for this session.
			 */
			c = (iscsi_conn_t *)m->msg_data;
			if (session_remove_connection(s, c) == True) {
				queue_prt(s->s_mgmtq, Q_SESS_NONIO,
				    "SES%x  Starting shutdown", s->s_num);

				/*
				 * If this is the last connection for this
				 * session send a message to the SAM-3 layer to
				 * shutdown.
				 */
				if (s->s_t10 != NULL) {
					t10_handle_disable(s->s_t10);
				}
				queue_message_set(s->s_t10q, 0,
				    msg_shutdown_rsp, 0);
				process = False;
			} else {

				/*
				 * Since this isn't the last connection for
				 * the session, acknowledge the connection
				 * request now since it's references from
				 * this session have been removed.
				 */
				queue_message_set(c->c_dataq, 0,
				    msg_shutdown_rsp, (void *)False);
			}
			break;

		case msg_initiator_name:
			nr = (name_request_t *)m->msg_data;
			s->s_i_name = strdup(nr->nr_name);

			/*
			 * Acknowledge the request by sending back an empty
			 * message.
			 */
			queue_message_set(nr->nr_q, 0, msg_initiator_name, 0);
			break;

		case msg_initiator_alias:
			nr = (name_request_t *)m->msg_data;
			s->s_i_alias = strdup(nr->nr_name);

			/*
			 * Acknowledge the request by sending back an empty
			 * message.
			 */
			queue_message_set(nr->nr_q, 0, msg_initiator_alias, 0);
			break;

		case msg_target_name:
			nr = (name_request_t *)m->msg_data;
			s->s_t_name = strdup(nr->nr_name);

			/*
			 * Acknowledge the request by sending back an empty
			 * message.
			 */
			queue_message_set(nr->nr_q, 0, msg_target_name, 0);
			break;

		case msg_mgmt_rqst:
			mgmt		= (mgmt_request_t *)m->msg_data;
			m->msg_data	= NULL;

			(void) pthread_mutex_lock(&mgmt->m_resp_mutex);
			buf = mgmt->m_u.m_resp;

			if ((s->s_type == SessionNormal) &&
			    (mgmt->m_request == mgmt_full_phase_statistics) &&
			    (strcmp(s->s_t_name, mgmt->m_targ_name) == 0)) {

				buf_add_tag(buf, XML_ELEMENT_CONN, Tag_Start);
				buf_add_tag(buf, s->s_i_name, Tag_String);
				if (s->s_i_alias != NULL) {
					xml_add_tag(buf, XML_ELEMENT_ALIAS,
					    s->s_i_alias);
				}

				/*
				 * Need to loop through the connections
				 * and create one time_connected tag for
				 * each. This will be needed once MC/S support
				 * is added.
				 */
				(void) snprintf(local_buf, sizeof (local_buf),
				    "%d",
				    mgmt->m_time - s->s_conn_head->c_up_at);
				xml_add_tag(buf, XML_ELEMENT_TIMECON,
				    local_buf);

				buf_add_tag(buf, XML_ELEMENT_STATS, Tag_Start);

				t10_targ_stat(s->s_t10, buf);

				buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End);
				buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End);
			}

			(void) pthread_mutex_unlock(&mgmt->m_resp_mutex);

			queue_message_set(mgmt->m_q, 0, msg_mgmt_rply, 0);

			break;

		default:
			queue_prt(s->s_mgmtq, Q_SESS_ERRS,
			    "SES%x  Unknown msg type (%d) from Connection",
			    s->s_num, m->msg_type);
			break;
		}
		queue_message_free(m);
	} while (process == True);

	return (NULL);
}
Beispiel #4
0
/*
 * []----
 * | sess_from_t10 -- handle messages from the T10 layer
 * []----
 */
void *
sess_from_t10(void *v)
{
	iscsi_sess_t	*s	= (iscsi_sess_t *)v;
	msg_t		*m;
	Boolean_t	process	= True;

	while (process == True) {
		m = queue_message_get(s->s_t10q);
		switch (m->msg_type) {
			case msg_cmd_data_rqst:
				queue_message_set(s->s_conn_head->c_dataq, 0,
				    msg_cmd_data_rqst, m->msg_data);
				break;

			case msg_cmd_data_in:
				queue_message_set(s->s_conn_head->c_dataq, 0,
				    msg_cmd_data_in, m->msg_data);
				break;

			case msg_cmd_cmplt:
				queue_message_set(s->s_conn_head->c_dataq, 0,
				    msg_cmd_cmplt, m->msg_data);
				break;

			case msg_shutdown_rsp:

				if (s->s_t10) {
					t10_handle_destroy(s->s_t10);
					s->s_t10 = NULL;
				}

				(void) pthread_mutex_lock(&s->s_mutex);
				s->s_state = SS_SHUTDOWN_CMPLT;
				(void) pthread_mutex_unlock(&s->s_mutex);

				session_free(s);

				/*
				 * Let the connection, which is the last, know
				 * about our completion of the shutdown.
				 */
				queue_message_set(s->s_conn_head->c_dataq, 0,
				    msg_shutdown_rsp, (void *)True);
				process		= False;
				s->s_state	= SS_FREE;
				break;

			default:
				queue_prt(s->s_mgmtq, Q_SESS_ERRS,
				    "SES%x  Unknown msg type (%d) from T10 ",
				    s->s_num, m->msg_type);
				queue_message_set(s->s_conn_head->c_dataq, 0,
				    m->msg_type, m->msg_data);
				break;
		}
		queue_message_free(m);
	}
	queue_free(s->s_t10q, NULL);
	util_title(s->s_mgmtq, Q_SESS_LOGIN, s->s_num, "End Session");
	free(s);
	return (NULL);
}