Пример #1
0
static int mgmt_ipc_session_update(queue_task_t *qtask)
{
	int rc, i, sid = qtask->req.u.session.sid;
	node_rec_t *rec = &qtask->req.u.session.rec;
	iscsi_session_t *session;
	struct iscsi_conn *conn;

	session = session_find_by_sid(sid);
	if (!session)
		return ISCSI_ERR_SESS_NOT_FOUND;

	if (rec->session.timeo.replacement_timeout >= 0)
		session->replacement_timeout =
				rec->session.timeo.replacement_timeout;

	if (rec->session.iscsi.FastAbort >= 0)
		session->fast_abort = rec->session.iscsi.FastAbort;

	if (rec->session.err_timeo.abort_timeout >= 0)
		session->abort_timeout = rec->session.err_timeo.abort_timeout;

	if (rec->session.err_timeo.lu_reset_timeout >= 0)
		session->lu_reset_timeout =
				rec->session.err_timeo.lu_reset_timeout;

	if (rec->session.err_timeo.tgt_reset_timeout >= 0)
		session->tgt_reset_timeout =
				rec->session.err_timeo.tgt_reset_timeout;

	for (i = 0; i < ISCSI_CONN_MAX; i++) {
		conn = &session->conn[i];

		if (rec->conn[i].timeo.noop_out_timeout >= 0)
			conn->noop_out_timeout =
				rec->conn[i].timeo.noop_out_timeout;

		if (rec->conn[i].timeo.noop_out_interval >= 0)
			conn->noop_out_interval =
				rec->conn[i].timeo.noop_out_interval;
	}

	rc = iscsi_session_set_params(session->conn);
	if (rc) {
		log_error("iscsi_session_set_params(): IPC error %d session"
			" [%02d]" , rc, sid);
		return ISCSI_ERR_INTERNAL;
	}

	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
	return ISCSI_SUCCESS;
}
Пример #2
0
static int
mgmt_ipc_session_info(queue_task_t *qtask)
{
	int sid = qtask->req.u.session.sid;
	iscsi_session_t *session;
	struct ipc_msg_session_state *info;

	if (!(session = session_find_by_sid(sid))) {
		log_debug(1, "session with sid %d not found!", sid);
		return ISCSI_ERR_SESS_NOT_FOUND;
	}

	info = &qtask->rsp.u.session_state;
	info->conn_state = session->conn[0].state;
	info->session_state = session->r_stage;

	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
	return ISCSI_SUCCESS;
}
Пример #3
0
static int
mgmt_ipc_session_getstats(queue_task_t *qtask)
{
	int sid = qtask->req.u.session.sid;
	iscsi_session_t *session;
	int rc;

	if (!(session = session_find_by_sid(sid)))
		return ISCSI_ERR_SESS_NOT_FOUND;

	rc = ipc->get_stats(session->t->handle,
		session->id, session->conn[0].id,
		(void *)&qtask->rsp.u.getstats,
		MGMT_IPC_GETSTATS_BUF_MAX);
	if (rc) {
		log_error("get_stats(): IPC error %d "
			"session [%02d]", rc, sid);
		return ISCSI_ERR_INTERNAL;
	}

	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
	return ISCSI_SUCCESS;
}
Пример #4
0
static int ctldev_handle(void)
{
	int rc, ev_size;
	struct iscsi_uevent *ev;
	iscsi_session_t *session = NULL;
	iscsi_conn_t *conn = NULL;
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
	struct nlmsghdr *nlh;
	struct iscsi_ev_context *ev_context;
	uint32_t sid = 0, cid = 0;

	log_debug(7, "in %s", __FUNCTION__);

	if ((rc = nl_read(ctrl_fd, nlm_ev,
		NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) {
		log_error("can not read nlm_ev, error %d", rc);
		return rc;
	}
	nlh = (struct nlmsghdr *)nlm_ev;
	ev = (struct iscsi_uevent *)NLMSG_DATA(nlm_ev);

	log_debug(7, "%s got event type %u", __FUNCTION__, ev->type);
	/* drivers like qla4xxx can be inserted after iscsid is started */
	switch (ev->type) {
	case ISCSI_KEVENT_CREATE_SESSION:
	/* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
	case ISCSI_UEVENT_CREATE_SESSION:
		drop_data(nlh);
		if (!ipc_ev_clbk)
			return 0;

		if (ipc_ev_clbk->create_session)
			ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
						    ev->r.c_session_ret.sid);
		return 0;
	case ISCSI_KEVENT_DESTROY_SESSION:
		drop_data(nlh);
		if (!ipc_ev_clbk)
			return 0;

		if (ipc_ev_clbk->destroy_session)
			ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
						     ev->r.d_session.sid);
		return 0;
	case ISCSI_KEVENT_RECV_PDU:
		sid = ev->r.recv_req.sid;
		cid = ev->r.recv_req.cid;
		break;
	case ISCSI_KEVENT_CONN_ERROR:
		sid = ev->r.connerror.sid;
		cid = ev->r.connerror.cid;
		break;
	case ISCSI_KEVENT_CONN_LOGIN_STATE:
		sid = ev->r.conn_login.sid;
		cid = ev->r.conn_login.cid;
		break;
	case ISCSI_KEVENT_UNBIND_SESSION:
		sid = ev->r.unbind_session.sid;
		/* session wide event so cid is 0 */
		cid = 0;
		break;
	case ISCSI_KEVENT_HOST_EVENT:
		switch (ev->r.host_event.code) {
		case ISCSI_EVENT_LINKUP:
			log_warning("Host%u: Link Up.",
				    ev->r.host_event.host_no);
			break;
		case ISCSI_EVENT_LINKDOWN:
			log_warning("Host%u: Link Down.",
				    ev->r.host_event.host_no);
			break;
		default:
			log_debug(7, "Host%u: Unknown host event: %u.",
				  ev->r.host_event.host_no,
				  ev->r.host_event.code);
		}

		drop_data(nlh);
		return 0;
	case ISCSI_KEVENT_PING_COMP:
		ping_event.host_no = ev->r.ping_comp.host_no;
		ping_event.pid = ev->r.ping_comp.pid;
		ping_event.status = ev->r.ping_comp.status;
		ping_event.active = 1;

		drop_data(nlh);
		return 0;
	default:
		if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
		    (ev->type > ISCSI_KEVENT_MAX))
			log_error("Unknown kernel event %d. You may want to "
				  " upgrade your iscsi tools.", ev->type);
		else
			/*
			 * If another app is using the interface we might
			 * see their
			 * stuff. Just drop it.
			 */
			log_debug(7, "Got unknown event %d. Dropping.",
				  ev->type);
		drop_data(nlh);
		return 0;
	}

	/* verify connection */
	session = session_find_by_sid(sid);
	if (!session) {
		/*
		 * this can happen normally when other apps are using the
		 * nl interface.
		 */
		log_debug(1, "Could not verify connection %d:%d. Dropping "
			   "event.", sid, cid);
		drop_data(nlh);
		return -ENXIO;
	}
	conn = &session->conn[0];

	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));

	ev_context = ipc_ev_clbk->get_ev_context(conn, ev_size);
	if (!ev_context) {
		log_error("Can not allocate memory for receive context.");
		drop_data(nlh);
		return -ENOMEM;
	}

	log_debug(6, "message real length is %d bytes, recv_handle %p",
		nlh->nlmsg_len, ev_context->data);

	if ((rc = nlpayload_read(ctrl_fd, ev_context->data,
				ev_size, 0)) < 0) {
		ipc_ev_clbk->put_ev_context(ev_context);
		log_error("can not read from NL socket, error %d", rc);
		/* retry later */
		return rc;
	}

	/*
	 * we sched these events because the handlers could call back
	 * into ctldev_handle
	 */
	switch (ev->type) {
	case ISCSI_KEVENT_RECV_PDU:
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
						   EV_CONN_RECV_PDU);
		break;
	case ISCSI_KEVENT_CONN_ERROR:
		memcpy(ev_context->data, &ev->r.connerror.error,
			sizeof(ev->r.connerror.error));
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
						   EV_CONN_ERROR);
		break;
	case ISCSI_KEVENT_CONN_LOGIN_STATE:
		memcpy(ev_context->data, &ev->r.conn_login.state,
			sizeof(ev->r.conn_login.state));
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
						   EV_CONN_LOGIN);
		break;
	case ISCSI_KEVENT_UNBIND_SESSION:
		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
						   EV_CONN_STOP);
		break;
	default:
		ipc_ev_clbk->put_ev_context(ev_context);
		log_error("unknown kernel event %d", ev->type);
		return -EEXIST;
	}

	if (rc)
		ipc_ev_clbk->put_ev_context(ev_context);
	return rc;
}