Exemplo n.º 1
0
void handle_iscsi_events(int fd)
{
	struct session *session;
	struct iet_event event;
	int res;

retry:
	if ((res = nl_read(fd, &event, sizeof(event))) < 0) {
		if (errno == EAGAIN)
			return;
		if (errno == EINTR)
			goto retry;
		log_error("read netlink fd (%d)", errno);
		exit(1);
	}

	log_debug(1, "conn %u session %llu target %u, state %u",
		  event.cid, event.sid, event.tid, event.state);

	switch (event.state) {
	case E_CONN_CLOSE:
		if (!(session = session_find_id(event.tid, event.sid))) {
			log_warning("session %llu not found?", event.sid);
			goto retry;
		}

		if (--session->conn_cnt <= 0)
			session_remove(session);
		break;
	default:
		log_error("%s(%d) %u\n", __FUNCTION__, __LINE__, event.state);
		exit(-1);
		break;
	}
}
Exemplo n.º 2
0
static int
kget_stats(uint64_t transport_handle, uint32_t sid, uint32_t cid,
	   char *statsbuf, int statsbuf_max)
{
	int rc;
	int ev_size;
	struct iscsi_uevent ev;
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
	struct nlmsghdr *nlh;
	struct iovec iov[2];

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

	memset(&ev, 0, sizeof(struct iscsi_uevent));

	ev.type = ISCSI_UEVENT_GET_STATS;
	ev.transport_handle = transport_handle;
	ev.u.get_stats.sid = sid;
	ev.u.get_stats.cid = cid;

	iov[1].iov_base = &ev;
	iov[1].iov_len = sizeof(ev);
	rc = __kipc_call(iov, 2);
	if (rc < 0)
		return rc;

	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_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));

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

	if (ev_size > statsbuf_max) {
		log_error("destanation buffer for statistics is "
			"not big enough to fit %d bytes", statsbuf_max);
		ev_size = statsbuf_max;
	}

	if ((rc = nlpayload_read(ctrl_fd, (void*)statsbuf, ev_size, 0)) < 0) {
		log_error("can not read from NL socket, error %d", rc);
		return rc;
	}

	return 0;
}
Exemplo n.º 3
0
static int kget_chap(uint64_t transport_handle, uint32_t host_no,
		     uint16_t chap_tbl_idx, uint32_t num_entries,
		     char *chap_buf, uint32_t *valid_chap_entries)
{
	int rc = 0;
	int ev_size;
	struct iscsi_uevent ev;
	struct iovec iov[2];
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
	struct nlmsghdr *nlh;

	memset(&ev, 0, sizeof(struct iscsi_uevent));

	ev.type = ISCSI_UEVENT_GET_CHAP;
	ev.transport_handle = transport_handle;
	ev.u.get_chap.host_no = host_no;
	ev.u.get_chap.chap_tbl_idx = chap_tbl_idx;
	ev.u.get_chap.num_entries = num_entries;

	iov[1].iov_base = &ev;
	iov[1].iov_len = sizeof(ev);
	rc = __kipc_call(iov, 2);
	if (rc < 0)
		return rc;

	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_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));

	if ((rc = nlpayload_read(ctrl_fd, (void *)chap_buf, ev_size, 0)) < 0) {
		log_error("can not read from NL socket, error %d", rc);
		return rc;
	}

	*valid_chap_entries = ev.u.get_chap.num_entries;

	return rc;
}
Exemplo n.º 4
0
static int kget_host_stats(uint64_t transport_handle, uint32_t host_no,
		     char *host_stats)
{
	int rc = 0;
	int ev_size;
	struct iscsi_uevent ev;
	struct iovec iov[2];
	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
	struct nlmsghdr *nlh;

	memset(&ev, 0, sizeof(struct iscsi_uevent));

	ev.type = ISCSI_UEVENT_GET_HOST_STATS;
	ev.transport_handle = transport_handle;
	ev.u.get_host_stats.host_no = host_no;

	iov[1].iov_base = &ev;
	iov[1].iov_len = sizeof(ev);
	rc = __kipc_call(iov, 2);
	if (rc < 0)
		return rc;

	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_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));

	if ((rc = nlpayload_read(ctrl_fd, (void *)host_stats,
				 ev_size, 0)) < 0) {
		log_error("can not read from NL socket, error %d", rc);
		return rc;
	}

	return rc;
}
Exemplo n.º 5
0
/* query external help program for s. num < 0 [keyword] or chapter number */
static void
external_help(const char *s, int num)
{
  long nbli = term_height()-3, li = 0;
  char buf[256], *str;
  const char *opt = "", *ar = "", *cdir = "";
  char *t, *help = GP_DATA->help;
  pariFILE *z;
  FILE *f;

  if (!has_ext_help()) pari_err(e_MISC,"no external help program");
  t = filter_quotes(s);
  if (num < 0)
    opt = "-k";
  else if (t[strlen(t)-1] != '@')
    ar = stack_sprintf("@%d",num);
#ifdef _WIN32
  if (*help=='@')
  {
    const char *basedir = win32_basedir();
    help++;
    cdir = stack_sprintf("%c:& cd %s & ", *basedir, basedir);
  }
#endif
  str=stack_sprintf("%s%s -fromgp %s %c%s%s%c",cdir,help,opt,
                                               SHELL_Q,t,ar,SHELL_Q);
  z = try_pipe(str,0); f = z->file;
  pari_free(t);
  while (fgets(buf, numberof(buf), f))
  {
    if (!strncmp("ugly_kludge_done",buf,16)) break;
    pari_puts(buf);
    if (nl_read(buf) && ++li > nbli) { pari_hit_return(); li = 0; }
  }
  pari_fclose(z);
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
int
ctldev_handle(int ctrl_fd)
{
	int rc;
	struct iscsi_uevent *ev;
	struct qelem *item;
	uiscsi_session_t *session = NULL;
	uiscsi_conn_t *conn = NULL;
	unsigned long recv_handle;
	struct nlmsghdr nlh;
	int ev_size;

	if ((rc = nl_read(ctrl_fd, &nlh, MSG_PEEK)) < 0) {
		log_error("can not read nlmsghdr, error %d", rc);
		return rc;
	}

	ev_size = nlh.nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
	recv_handle = (unsigned long)calloc(1, ev_size);
	if (!recv_handle) {
		log_error("can not allocate memory for receive handle");
		return -ENOMEM;
	}

	log_debug(6, "message real length is %d bytes, recv_handle %p",
		nlh.nlmsg_len, (void*)recv_handle);

	if ((rc = nlpayload_read(ctrl_fd, (void*)recv_handle,
				ev_size, 0)) < 0) {
		log_error("can not read from NL socket, error %d", rc);
		return rc;
	}
	ev = (struct iscsi_uevent *)recv_handle;

	/* verify connection */
	item = provider[0].sessions.q_forw;
	while (item != &provider[0].sessions) {
		int i;
		session = (uiscsi_session_t *)item;
		for (i=0; i<ISCSI_CNX_MAX; i++) {
			if (&session->cnx[i] == (uiscsi_conn_t*)
					iscsi_ptr(ev->r.recv_req.cnx_handle) ||
			    &session->cnx[i] == (uiscsi_conn_t*)
					iscsi_ptr(ev->r.cnxerror.cnx_handle)) {
				conn = &session->cnx[i];
				break;
			}
		}
		item = item->q_forw;
	}

	if (ev->type == ISCSI_KEVENT_RECV_PDU) {
		if (conn == NULL) {
			log_error("could not verify connection 0x%p for "
				  "event RECV_PDU", conn);
			return -ENXIO;
		}

		/* produce an event, so session manager will handle */
		queue_produce(session->queue, EV_CNX_RECV_PDU, conn,
			sizeof(unsigned long), &recv_handle);
		actor_schedule(&session->mainloop);

	} else if (ev->type == ISCSI_KEVENT_CNX_ERROR) {
		if (conn == NULL) {
			log_error("could not verify connection 0x%p for "
				  "event CNX_ERR", conn);
			return -ENXIO;
		}

		/* produce an event, so session manager will handle */
		queue_produce(session->queue, EV_CNX_ERROR, conn,
			sizeof(unsigned long), (void*)&ev->r.cnxerror.error);
		actor_schedule(&session->mainloop);

	} else {
		log_error("unknown kernel event %d", ev->type);
		return -EEXIST;
	}

	return 0;
}