Beispiel #1
0
int criu_restore(void)
{
	int ret = -1;
	CriuReq req	= CRIU_REQ__INIT;
	CriuResp *resp	= NULL;

	saved_errno = 0;

	req.type	= CRIU_REQ_TYPE__RESTORE;
	req.opts	= opts;

	ret = send_req_and_recv_resp(&req, &resp);
	if (ret)
		goto exit;

	if (resp->success)
		ret = resp->restore->pid;
	else
		ret = -EBADE;

exit:
	if (resp)
		criu_resp__free_unpacked(resp, NULL);

	errno = saved_errno;

	return ret;
}
Beispiel #2
0
int criu_dump(void)
{
	int ret = -1;
	CriuReq req	= CRIU_REQ__INIT;
	CriuResp *resp	= NULL;

	saved_errno = 0;

	req.type	= CRIU_REQ_TYPE__DUMP;
	req.opts	= opts;

	ret = send_req_and_recv_resp(&req, &resp);
	if (ret)
		goto exit;

	if (resp->success) {
		if (resp->dump->has_restored && resp->dump->restored)
			ret = 1;
		else
			ret = 0;
	} else
		ret = -EBADE;

exit:
	if (resp)
		criu_resp__free_unpacked(resp, NULL);

	errno = saved_errno;

	return ret;
}
Beispiel #3
0
int criu_check(void)
{
	int ret = -1;
	CriuReq req	= CRIU_REQ__INIT;
	CriuResp *resp	= NULL;

	saved_errno = 0;

	req.type	= CRIU_REQ_TYPE__CHECK;

	ret = send_req_and_recv_resp(&req, &resp);
	if (ret)
		goto exit;

	ret = resp->success ? 0 : -EBADE;

exit:
	if (resp)
		criu_resp__free_unpacked(resp, NULL);

	errno = saved_errno;

	return ret;
}
Beispiel #4
0
int criu_restore_child(void)
{
	int sks[2], pid, ret = -1;
	CriuReq req	= CRIU_REQ__INIT;
	CriuResp *resp	= NULL;

	if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sks))
		goto out;

	pid = fork();
	if (pid < 0)
		goto err;

	if (pid == 0) {
		sigset_t mask;
		char fds[11];

		/*
		 * Unblock SIGCHLD.
		 *
		 * The caller of this function is supposed to have
		 * this signal blocked. Otherwise it risks to get
		 * into situation, when this routine is not yet
		 * returned, but the restore subtree exits and
		 * emits the SIGCHLD.
		 *
		 * In turn, unblocked SIGCHLD is required to make
		 * criu restoration process work -- it catches
		 * subtasks restore errors in this handler.
		 */

		sigemptyset(&mask);
		sigaddset(&mask, SIGCHLD);
		sigprocmask(SIG_UNBLOCK, &mask, NULL);

		close(sks[0]);
		sprintf(fds, "%d", sks[1]);

		execlp("criu", "criu", "swrk", fds, NULL);
		exit(1);
	}

	close(sks[1]);

	req.type	= CRIU_REQ_TYPE__RESTORE;
	req.opts	= opts;

	req.opts->has_rst_sibling = true;
	req.opts->rst_sibling = true;

	ret = send_req_and_recv_resp_sk(sks[0], &req, &resp);

	close(sks[0]);
	waitpid(pid, NULL, 0);

	if (!ret) {
		ret = resp->success ? resp->restore->pid : -EBADE;
		criu_resp__free_unpacked(resp, NULL);
	}

out:
	return ret;

err:
	close(sks[1]);
	close(sks[0]);
	goto out;
}
Beispiel #5
0
int criu_dump_iters(int (*more)(criu_predump_info pi))
{
	int ret = -1, fd = -1, uret;
	CriuReq req	= CRIU_REQ__INIT;
	CriuResp *resp	= NULL;

	saved_errno = 0;

	req.type	= CRIU_REQ_TYPE__PRE_DUMP;
	req.opts	= opts;

	ret = -EINVAL;
	/*
	 * Self-dump in iterable manner is tricky and
	 * not supported for the moment.
	 *
	 * Calls w/o iteration callback is, well, not
	 * allowed either.
	 */
	if (!opts->has_pid || !more)
		goto exit;

	ret = -ECONNREFUSED;
	fd = criu_connect();
	if (fd < 0)
		goto exit;

	while (1) {
		ret = send_req_and_recv_resp_sk(fd, &req, &resp);
		if (ret)
			goto exit;

		if (!resp->success) {
			ret = -EBADE;
			goto exit;
		}

		uret = more(NULL);
		if (uret < 0) {
			ret = uret;
			goto exit;
		}

		criu_resp__free_unpacked(resp, NULL);

		if (uret == 0)
			break;
	}

	req.type = CRIU_REQ_TYPE__DUMP;
	ret = send_req_and_recv_resp_sk(fd, &req, &resp);
	if (!ret)
		ret = (resp->success ? 0 : -EBADE);
exit:
	if (fd >= 0)
		close(fd);
	if (resp)
		criu_resp__free_unpacked(resp, NULL);

	errno = saved_errno;

	return ret;
}
Beispiel #6
0
int main(int argc, char *argv[])
{
	CriuReq req		= CRIU_REQ__INIT;
	CriuResp *resp		= NULL;
	int fd, dir_fd;
	int ret = 0;
	struct sockaddr_un addr;
	socklen_t addr_len;

	if (argc != 3) {
		fprintf(stderr, "Usage: test-c criu-service.socket imgs_dir");
		return -1;
	}

	/*
	 * Open a directory, in which criu will
	 * put images
	 */

	puts(argv[2]);
	dir_fd = open(argv[2], O_DIRECTORY);
	if (dir_fd == -1) {
		perror("Can't open imgs dir");
		return -1;
	}

	/*
	 * Set "DUMP" type of request.
	 * Allocate CriuDumpReq.
	 */
	req.type			= CRIU_REQ_TYPE__DUMP;
	req.opts			= malloc(sizeof(CriuOpts));
	if (!req.opts) {
			perror("Can't allocate memory for dump request");
			return -1;
	}

	criu_opts__init(req.opts);

	/*
	 * Set dump options.
	 * Checkout more in protobuf/rpc.proto.
	 */
	req.opts->has_leave_running	= true;
	req.opts->leave_running		= true;
	req.opts->images_dir_fd		= dir_fd;
	req.opts->has_log_level		= true;
	req.opts->log_level		= 4;

	/*
	 * Connect to service socket
	 */
	fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
	if (fd == -1) {
		perror("Can't create socket");
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_LOCAL;

	strcpy(addr.sun_path, argv[1]);

	addr_len = strlen(addr.sun_path) + sizeof(addr.sun_family);

	ret = connect(fd, (struct sockaddr *) &addr, addr_len);
	if (ret == -1) {
		perror("Cant connect to socket");
		goto exit;
	}

	/*
	 * Send request
	 */
	ret = send_req(fd, &req);
	if (ret == -1) {
		perror("Can't send request");
		goto exit;
	}

	/*
	 * Recv response
	 */
	resp = recv_resp(fd);
	if (!resp) {
		perror("Can't recv response");
		ret = -1;
		goto exit;
	}

	if (resp->type != CRIU_REQ_TYPE__DUMP) {
		perror("Unexpected response type");
		ret = -1;
		goto exit;
	}

	/*
	 * Check response.
	 */
	if (resp->success)
		puts("Success");
	else {
		puts("Fail");
		ret = -1;
		goto exit;
	}

	if (resp->dump->has_restored && resp->dump->restored)
		puts("Restored");

exit:
	close(fd);
	close(dir_fd);
	if (resp)
		criu_resp__free_unpacked(resp, NULL);
	return ret;
}