xref: /netbsd-src/tests/dev/md/h_mdserv.c (revision b58602814f44cdb10d1ce70b9ef75bf29672fcc0)
1*b5860281Sandvar /*	$NetBSD: h_mdserv.c,v 1.5 2021/09/16 22:19:11 andvar Exp $	*/
248e1b6d6Spooka 
348e1b6d6Spooka #include <sys/types.h>
448e1b6d6Spooka #include <sys/mman.h>
548e1b6d6Spooka #include <sys/ioctl.h>
648e1b6d6Spooka 
748e1b6d6Spooka #include <dev/md.h>
848e1b6d6Spooka 
9401a8e7aSpooka #include <err.h>
10401a8e7aSpooka #include <errno.h>
1148e1b6d6Spooka #include <fcntl.h>
12401a8e7aSpooka #include <pthread.h>
13401a8e7aSpooka #include <stdio.h>
14401a8e7aSpooka #include <stdlib.h>
1548e1b6d6Spooka #include <unistd.h>
1648e1b6d6Spooka 
1748e1b6d6Spooka #include <rump/rump.h>
1848e1b6d6Spooka #include <rump/rump_syscalls.h>
1948e1b6d6Spooka 
2048e1b6d6Spooka #define MDSIZE (1024*1024)
2148e1b6d6Spooka 
22401a8e7aSpooka #define REQUIRE(a, msg) if ((a) != 0) err(1, msg);
23401a8e7aSpooka 
24401a8e7aSpooka static void *
prober(void * arg)25401a8e7aSpooka prober(void *arg)
2648e1b6d6Spooka {
27401a8e7aSpooka 	int fd, error;
28401a8e7aSpooka 	char buf[4];
29401a8e7aSpooka 	ssize_t n;
30401a8e7aSpooka 
31401a8e7aSpooka 	fd = rump_sys_open(arg, O_RDONLY);
32401a8e7aSpooka 	for (;;) {
33401a8e7aSpooka 		n = rump_sys_read(fd, buf, sizeof(buf));
34401a8e7aSpooka 
35401a8e7aSpooka 		switch (n) {
36401a8e7aSpooka 		case 4:
37401a8e7aSpooka 			error = 0;
38401a8e7aSpooka 			goto out;
39401a8e7aSpooka 
40401a8e7aSpooka 		case -1:
41401a8e7aSpooka 			if (errno == ENXIO) {
42401a8e7aSpooka 				usleep(1000);
43401a8e7aSpooka 				continue;
44401a8e7aSpooka 			}
45401a8e7aSpooka 
46401a8e7aSpooka 			/* FALLTHROUGH */
47401a8e7aSpooka 		default:
48401a8e7aSpooka 			error = EPIPE;
49401a8e7aSpooka 			goto out;
50401a8e7aSpooka 		}
51401a8e7aSpooka 	}
52401a8e7aSpooka  out:
53401a8e7aSpooka 
54401a8e7aSpooka 	error = rump_daemonize_done(error);
55401a8e7aSpooka 	REQUIRE(error, "rump_daemonize_done");
56401a8e7aSpooka 
57401a8e7aSpooka 	if (error)
58401a8e7aSpooka 		exit(1);
59401a8e7aSpooka 
60401a8e7aSpooka 	return NULL;
61401a8e7aSpooka }
62401a8e7aSpooka 
63401a8e7aSpooka int
main(int argc,char * argv[])64401a8e7aSpooka main(int argc, char *argv[])
65401a8e7aSpooka {
66401a8e7aSpooka 	pthread_t pt;
6748e1b6d6Spooka 	struct md_conf md;
68401a8e7aSpooka 	int fd, error;
69401a8e7aSpooka 
70401a8e7aSpooka 	if (argc != 2)
71401a8e7aSpooka 		exit(1);
7248e1b6d6Spooka 
7358a824fcSpooka 	md.md_addr = calloc(1, MDSIZE);
7448e1b6d6Spooka 	md.md_size = MDSIZE;
7548e1b6d6Spooka 	md.md_type = MD_UMEM_SERVER;
7648e1b6d6Spooka 
77401a8e7aSpooka 	error = rump_daemonize_begin();
78401a8e7aSpooka 	REQUIRE(error, "rump_daemonize_begin");
79401a8e7aSpooka 
80401a8e7aSpooka 	error = rump_init();
81401a8e7aSpooka 	REQUIRE(error, "rump_init");
82401a8e7aSpooka 
83401a8e7aSpooka 	error = rump_init_server("unix://commsock");
84401a8e7aSpooka 	REQUIRE(error, "init server");
85401a8e7aSpooka 
86401a8e7aSpooka 	if ((fd = rump_sys_open(argv[1], O_RDWR)) == -1)
87401a8e7aSpooka 		err(1, "open");
88401a8e7aSpooka 
89401a8e7aSpooka 	/*
90401a8e7aSpooka 	 * Now, configuring the md driver also causes our process
91fe0f8107Spooka 	 * to start acting as the worker for the md.  Splitting it
92401a8e7aSpooka 	 * into two steps in the driver is not easy, since md is
93401a8e7aSpooka 	 * supposed to be unconfigured when the process dies
94401a8e7aSpooka 	 * (process may exit between calling ioctl1 and ioctl2).
95fe0f8107Spooka 	 * So, start a probe thread which attempts to read the md
96401a8e7aSpooka 	 * and declares the md as configured when the read is
97*b5860281Sandvar 	 * successful.
98401a8e7aSpooka 	 */
99401a8e7aSpooka 	error = pthread_create(&pt, NULL, prober, argv[1]);
100401a8e7aSpooka 	REQUIRE(error, "pthread_create");
101401a8e7aSpooka 	pthread_detach(pt);
102401a8e7aSpooka 
103401a8e7aSpooka 	if (rump_sys_ioctl(fd, MD_SETCONF, &md) == -1) {
104401a8e7aSpooka 		rump_daemonize_done(errno);
105401a8e7aSpooka 		exit(1);
106401a8e7aSpooka 	}
107401a8e7aSpooka 
108401a8e7aSpooka 	return 0;
10948e1b6d6Spooka }
110