Пример #1
0
Файл: io.c Проект: CPFL/gxen
int libxenvchan_write(struct libxenvchan *ctrl, const void *data, size_t size)
{
	int avail;
	if (!libxenvchan_is_open(ctrl))
		return -1;
	if (ctrl->blocking) {
		size_t pos = 0;
		while (1) {
			avail = fast_get_buffer_space(ctrl, size - pos);
			if (pos + avail > size)
				avail = size - pos;
			if (avail)
				pos += do_send(ctrl, data + pos, avail);
			if (pos == size)
				return pos;
			if (libxenvchan_wait(ctrl))
				return -1;
			if (!libxenvchan_is_open(ctrl))
				return -1;
		}
	} else {
		avail = fast_get_buffer_space(ctrl, size);
		if (size > avail)
			size = avail;
		if (size == 0)
			return 0;
		return do_send(ctrl, data, size);
	}
}
Пример #2
0
int libvchan_wait(libvchan_t *ctrl) {
    int ret = -2; /* invalid, so can be distinguished from real
                     libxenvchan_wait return code */
    struct xs_handle *xs;

    if (ctrl->xenvchan->is_server && libxenvchan_is_open(ctrl->xenvchan) == 2) {
        /* In case of vchan server waiting for a client, we'll not receive any
         * notification if the remote domain dies before connecting. Because of
         * that, check periodically if remote domain is still alive while
         * waiting for a connection. Actually this doesn't cover all the cases
         * - if remote domain is still alive, but remote process dies before
         * connecting, we'll also not receive any notification. But this, in
         * most cases, can be solved by application using libvchan.
         *
         * During normal operation this shouldn't be long - in most cases vchan
         * client will connect almost instantly. So this sleep(10) loop will
         * not hurt. Alternativelly it could be implemented with
         * xs_watch("@releaseDomain"), but such approach will slow down most
         * common execution path (xs_open+xs_watch even if client connects
         * right away).
         */
        while (ret == -2 && libxenvchan_is_open(ctrl->xenvchan) == 2) {
            fd_set rd_set;
            struct timeval tv = { 10, 0 };
            int vchan_fd = libxenvchan_fd_for_select(ctrl->xenvchan);
            FD_ZERO(&rd_set);
            FD_SET(vchan_fd, &rd_set);
            switch (select(vchan_fd+1, &rd_set, NULL, NULL, &tv)) {
                case 0:
                    if (!libvchan__check_domain_alive(ctrl->xc_handle, ctrl->remote_domain))
                        return -1;
                    break;
                case 1:
                    /* break the loop */
                    ret = -1;
                    break;
                default:
                    if (errno == EINTR)
                        break;
                    perror("select");
                    return -1;
            }
        }
    }
    ret = libxenvchan_wait(ctrl->xenvchan);
    if (ctrl->xs_path) {
        /* remove xenstore entry at first client connection */
        xs = xs_open(0);
        if (xs) {
            /* if xenstore connection failed just do not remove entries, but do
             * not abort whole function, especially still free the memory
             */
            xs_rm(xs, 0, ctrl->xs_path);
            xs_close(xs);
        }
        free(ctrl->xs_path);
        ctrl->xs_path = NULL;
    }
    return ret;
}
Пример #3
0
int libvchan_is_open(libvchan_t *ctrl) {
    int ret;
    struct evtchn_status evst;

    ret = libxenvchan_is_open(ctrl->xenvchan);
    if (ret == 2) {
        if (!libvchan__check_domain_alive(ctrl->xc_handle, ctrl->remote_domain))
            return VCHAN_DISCONNECTED;
        return VCHAN_WAITING;
    }
    if (!ret)
        return VCHAN_DISCONNECTED;
    /* slow check in case of domain destroy */
    evst.port = ctrl->xenvchan->event_port;
    evst.dom = DOMID_SELF;
    if (xc_evtchn_status(ctrl->xc_handle, &evst)) {
        perror("xc_evtchn_status");
        return VCHAN_DISCONNECTED;
    }
    if (evst.status != EVTCHNSTAT_interdomain) {
        if (!ctrl->xenvchan->is_server)
            ctrl->xenvchan->ring->srv_live = 0;
        return VCHAN_DISCONNECTED;
    }
    return VCHAN_CONNECTED;
}
Пример #4
0
Файл: io.c Проект: CPFL/gxen
int libxenvchan_read(struct libxenvchan *ctrl, void *data, size_t size)
{
	while (1) {
		int avail = fast_get_data_ready(ctrl, size);
		if (avail && size > avail)
			size = avail;
		if (avail)
			return do_recv(ctrl, data, size);
		if (!libxenvchan_is_open(ctrl))
			return -1;
		if (!ctrl->blocking)
			return 0;
		if (libxenvchan_wait(ctrl))
			return -1;
	}
}
Пример #5
0
Файл: io.c Проект: CPFL/gxen
/**
 * returns 0 if no buffer space is available, -1 on error, or size on success
 */
int libxenvchan_send(struct libxenvchan *ctrl, const void *data, size_t size)
{
	int avail;
	while (1) {
		if (!libxenvchan_is_open(ctrl))
			return -1;
		avail = fast_get_buffer_space(ctrl, size);
		if (size <= avail)
			return do_send(ctrl, data, size);
		if (!ctrl->blocking)
			return 0;
		if (size > wr_ring_size(ctrl))
			return -1;
		if (libxenvchan_wait(ctrl))
			return -1;
	}
}