Esempio n. 1
0
int hyper_setup_netlink_listener(struct hyper_event *e)
{
	int fd;
	struct sockaddr_nl sa;

	memset(&sa, 0, sizeof(sa));
	sa.nl_family = AF_NETLINK;
	sa.nl_groups = 0xffffffff;
	fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
	if (fd < 0) {
		perror("failed to create netlink socket");
		return -1;
	}
	if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
		perror("failed to bind netlink socket");
		close(fd);
		return -1;
	}
	e->fd = fd;

	if (hyper_init_event(e, &hyper_devfd_ops, NULL) < 0) {
		hyper_reset_event(e);
		return -1;
	}

	return 0;
}
Esempio n. 2
0
int hyper_add_event(int efd, struct hyper_event *de)
{
	struct epoll_event event = {
		.events		= EPOLLIN,
		.data.ptr	= de,
	};

	if (hyper_setfd_nonblock(de->fd) < 0) {
		perror("set fd nonblock failed");
		return -1;
	}

	fprintf(stdout, "%s add event fd %d, %p\n", __func__, de->fd, de->ops);

	if (epoll_ctl(efd, EPOLL_CTL_ADD, de->fd, &event) < 0) {
		perror("epoll_ctl fd failed");
		return -1;
	}

	return 0;
}

void hyper_event_hup(struct hyper_event *de, int efd)
{
	if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
		perror("epoll_ctl del epoll event failed");
	close(de->fd);
	hyper_reset_event(de);
}

int hyper_handle_event(int efd, struct epoll_event *event)
{
	struct hyper_event *de = event->data.ptr;

	if (event->events & EPOLLHUP) {
		fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
			__func__, de, de->fd, de->ops);
		if (de->ops->hup)
			de->ops->hup(de, efd);
		return 0;
	} else if (event->events & EPOLLIN) {
		return de->ops->read(de);
	} else if (event->events & EPOLLERR) {
		fprintf(stderr, "get epoll err of not epool in event\n");
		return -1;
	}

	fprintf(stdout, "%s get unknown event %d\n", __func__, event->events);
	return -1;
}
Esempio n. 3
0
int hyper_start_container(struct hyper_container *container,
			  int utsns, int ipcns, struct hyper_pod *pod)
{
	int stacksize = getpagesize() * 4;
	struct hyper_container_arg arg = {
		.c	= container,
		.utsns	= utsns,
		.ipcns	= ipcns,
		.pipe	= {-1, -1},
	};
	int flags = CLONE_NEWNS | SIGCHLD;
	char path[128];
	uint32_t type;
	void *stack;
	int pid;

	if (container->image == NULL || container->exec.argv == NULL) {
		fprintf(stdout, "container root image %s, argv %p\n",
			container->image, container->exec.argv);
		goto fail;
	}

	if (hyper_setup_pty(container) < 0) {
		fprintf(stderr, "setup pty device for container failed\n");
		goto fail;
	}

	if (pipe2(arg.pipe, O_CLOEXEC) < 0) {
		perror("create pipe between pod init execcmd failed");
		goto fail;
	}

	if (hyper_watch_exec_pty(&container->exec, pod) < 0) {
		fprintf(stderr, "faile to watch container pty\n");
		goto fail;
	}

	stack = malloc(stacksize);
	if (stack == NULL) {
		perror("fail to allocate stack for container init");
		goto fail;
	}

	pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
	free(stack);
	if (pid < 0) {
		perror("create child process failed");
		goto fail;
	}
	sprintf(path, "/proc/%d/ns/mnt", pid);

	container->ns = open(path, O_RDONLY | O_CLOEXEC);
	if (container->ns < 0) {
		perror("open container mount ns failed");
		goto fail;
	}

	/* wait for ready message */
	if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
		fprintf(stderr, "wait for container started failed\n");
		goto fail;
	}

	container->exec.pid = pid;
	list_add_tail(&container->exec.list, &pod->exec_head);
	container->exec.ref++;

	close(arg.pipe[0]);
	close(arg.pipe[1]);

	fprintf(stdout, "container %s,init pid %d,ref %d\n", container->id, pid, container->exec.ref);
	return 0;
fail:
	close(arg.pipe[0]);
	close(arg.pipe[1]);
	close(container->ns);
	hyper_reset_event(&container->exec.e);
	hyper_reset_event(&container->exec.errev);
	container->ns = -1;
	fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
	container->exec.code = -1;
	container->exec.seq = 0;
	container->exec.ref = 0;
	return -1;
}
Esempio n. 4
0
int hyper_add_event(int efd, struct hyper_event *de, int flag)
{
	struct epoll_event event = {
		.events		= flag,
		.data.ptr	= de,
	};

	de->flag = flag;
	if (hyper_setfd_nonblock(de->fd) < 0) {
		perror("set fd nonblock failed");
		return -1;
	}

	fprintf(stdout, "%s add event fd %d, %p\n", __func__, de->fd, de->ops);

	if (epoll_ctl(efd, EPOLL_CTL_ADD, de->fd, &event) < 0) {
		perror("epoll_ctl fd failed");
		return -1;
	}

	return 0;
}

int hyper_modify_event(int efd, struct hyper_event *de, int flag)
{
	struct epoll_event event = {
		.events		= flag,
		.data.ptr	= de,
	};

	if (de->flag == flag)
		return 0;

	de->flag = flag;
	fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
			__func__, de->fd, de, flag);

	if (epoll_ctl(efd, EPOLL_CTL_MOD, de->fd, &event) < 0) {
		perror("epoll_ctl fd failed");
		return -1;
	}

	return 0;
}

static int hyper_getmsg_len(struct hyper_event *de, uint32_t *len)
{
	struct hyper_buf *buf = &de->rbuf;

	if (buf->get < de->ops->len_offset + 4)
		return -1;

	*len = hyper_get_be32(buf->data + de->ops->len_offset);
	return 0;
}

int hyper_event_read(struct hyper_event *de, int efd)
{
	struct hyper_buf *buf = &de->rbuf;
	uint32_t len = 4;
	uint8_t data[4];
	int offset = de->ops->len_offset;
	int end = offset + 4;
	int size;

	fprintf(stdout, "%s\n", __func__);

	while (hyper_getmsg_len(de, &len) < 0) {
		size = read(de->fd, buf->data + buf->get, end - buf->get);
		if (size > 0) {
			buf->get += size;
			fprintf(stdout, "already read %" PRIu32 " bytes data\n",
				buf->get);

			if (de->ops->ack) {
				/* control channel, need ack */
				hyper_set_be32(data, size);
				hyper_send_msg(de->fd, NEXT, 4, data);
			}
			continue;
		}

		if (errno == EINTR)
			continue;

		if (errno != EAGAIN && size != 0) {
			perror("fail to read");
			return -1;
		}

		return 0;
	}

	fprintf(stdout, "get length %" PRIu32"\n", len);
	if (len > buf->size) {
		fprintf(stderr, "get length %" PRIu32", too long\n", len);
		return -1;
	}

	while (buf->get < len) {
		size = read(de->fd, buf->data + buf->get, len - buf->get);
		if (size > 0) {
			buf->get += size;
			fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n",
				size, buf->get);
			if (de->ops->ack) {
				/* control channel, need ack */
				hyper_set_be32(data, size);
				hyper_send_msg(de->fd, NEXT, 4, data);
			}

			continue;
		}

		if (errno == EINTR)
			continue;

		if (errno != EAGAIN && size != 0) {
			perror("fail to read");
			return -1;
		}

		/* size == 0 : No one connect to qemu socket */
		return 0;
	}

	/* get the whole data */
	if (de->ops->handle(de, len) != 0)
		return -1;

	/* len: length of the already get new data */
	buf->get -= len;
	memmove(buf->data, buf->data + len, buf->get);

	return 0;
}

int hyper_event_write(struct hyper_event *de)
{
	struct hyper_buf *buf = &de->wbuf;
	uint32_t len = 0;
	int size = 0;

	while (len < buf->get) {
		size = write(de->fd, buf->data + len, buf->get - len);
		if (size <= 0) {
			if (errno == EINTR)
				continue;
			if (errno == EAGAIN || size == 0)
				break;
			return -1;
		}
		len += size;
	}

	buf->get -= len;
	memmove(buf->data, buf->data + len, buf->get);

	if (buf->get == 0) {
		hyper_modify_event(ctl.efd, de, EPOLLIN);
	}

	return 0;
}

void hyper_event_hup(struct hyper_event *de, int efd)
{
	if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
		perror("epoll_ctl del epoll event failed");
	hyper_reset_event(de);
}

int hyper_handle_event(int efd, struct epoll_event *event)
{
	struct hyper_event *de = event->data.ptr;
	fprintf(stdout, "%s get event %d, de %p, fd %d. ops %p\n",
			__func__, event->events, de, de->fd, de->ops);

	/* do not handle hup event if have in event */
	if ((event->events & EPOLLIN) && de->ops->read) {
		fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n",
			__func__, de, de->fd, de->ops);
		if (de->ops->read && de->ops->read(de, efd) < 0)
			return -1;
	} else if (event->events & EPOLLHUP) {
		fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
			__func__, de, de->fd, de->ops);
		if (de->ops->hup)
			de->ops->hup(de, efd);
		return 0;
	}

	if (event->events & EPOLLOUT) {
		fprintf(stdout, "%s event EPOLLOUT, de %p, fd %d, %p\n",
			__func__, de, de->fd, de->ops);
		if (de->ops->write && de->ops->write(de) < 0)
			return -1;
	}

	if (event->events & EPOLLERR) {
		fprintf(stderr, "get epoll err of not epool in event\n");
		if (de->ops->hup)
			de->ops->hup(de, efd);
		return 0;
	}

	return 0;
}