예제 #1
0
static int
__ksession_call(int ctrl_fd, void *iov_base, int iov_len)
{
	int rc;
	struct iovec iov;
	struct iscsi_uevent *ev = iov_base;
	iscsi_uevent_e type = ev->type;

	iov.iov_base = iov_base;
	iov.iov_len = iov_len;

	if ((rc = ctldev_writev(ctrl_fd, type, &iov, 1)) < 0) {
		return rc;
	}

	do {
		if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
					 sizeof(*ev), MSG_PEEK)) < 0) {
			return rc;
		}
		if (ev->type != type) {
			/*
			 * receive and queue async. event which as of
			 * today could be:
			 *	- CNX_ERROR
			 *	- RECV_PDU
			 */
			ctldev_handle(ctrl_fd);
		} else {
			if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
						 sizeof(*ev), 0)) < 0) {
				return rc;
			}
			break;
		}
	} while (ev->type != type);

	return rc;
}
예제 #2
0
파일: netlink.c 프로젝트: cleech/open-iscsi
/*
 * __kipc_call() should never block. Therefore
 * Netlink's xmit logic is serialized. This means we do not allocate on
 * xmit path. Instead we reuse nlm_sendbuf buffer.
 *
 * Transport must assure non-blocking operations for:
 *
 *	- session_create()
 *	- conn_create()
 *	- conn_bind()
 *	_ set_param()
 *	- conn_start()
 *	- conn_stop()
 *
 * Its OK to block for cleanup for short period of time in operatations for:
 *
 *	- conn_destroy()
 *	- session_destroy()
 *
 * FIXME: interface needs to be extended to allow longer blocking on
 *        cleanup. (Dima)
 */
static int
__kipc_call(struct iovec *iovp, int count)
{
	int rc, iferr;
	struct iscsi_uevent *ev = iovp[1].iov_base;
	enum iscsi_uevent_e type = ev->type;

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

	rc = kwritev(type, iovp, count);

	do {
		if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
					 sizeof(*ev), MSG_PEEK)) < 0) {
			return rc;
		}
		if (ev->type != type) {
			log_debug(1, "expecting event %d, got %d, handling...",
				  type, ev->type);
			if (ev->type == ISCSI_KEVENT_IF_ERROR) {
				if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
							 sizeof(*ev), 0)) < 0) {
					return rc;
				}
				/*
				 * iferror is u32, but the kernel returns
				 * negative errno values for errors.
				 */
				iferr = ev->iferror;

				if (iferr == -ENOSYS)
					/* not fatal so let caller handle log */
					log_debug(1, "Received iferror %d: %s.",
						  iferr, strerror(-iferr));
				else if (iferr < 0)
					log_error("Received iferror %d: %s.",
						   iferr, strerror(-iferr));
				else
					log_error("Received iferror %d.",
						   iferr);
				return ev->iferror;
			}
			/*
			 * receive and queue async. event which as of
			 * today could be:
			 *	- CONN_ERROR
			 *	- RECV_PDU
			 */
			ctldev_handle();
		} else if (ev->type == ISCSI_UEVENT_GET_STATS) {
			/* kget_stats() will read */
			return 0;
		} else if (ev->type == ISCSI_UEVENT_GET_CHAP) {
			/* kget_chap() will read */
			return 0;
		} else if (ev->type == ISCSI_UEVENT_GET_HOST_STATS) {
			/* kget_host_stats() will read */
			return 0;

		} else {
			if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
						 sizeof(*ev), 0)) < 0) {
				return rc;
			}
			break;
		}
	} while (ev->type != type);

	return rc;
}