xref: /freebsd/contrib/netbsd-tests/dev/md/h_mdserv.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
1 /*	$NetBSD: h_mdserv.c,v 1.4 2011/02/10 13:29:02 pooka Exp $	*/
2 
3 #include <sys/types.h>
4 #include <sys/mman.h>
5 #include <sys/ioctl.h>
6 
7 #include <dev/md.h>
8 
9 #include <err.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 #include <rump/rump.h>
18 #include <rump/rump_syscalls.h>
19 
20 #define MDSIZE (1024*1024)
21 
22 #define REQUIRE(a, msg) if ((a) != 0) err(1, msg);
23 
24 static void *
25 prober(void *arg)
26 {
27 	int fd, error;
28 	char buf[4];
29 	ssize_t n;
30 
31 	fd = rump_sys_open(arg, O_RDONLY);
32 	for (;;) {
33 		n = rump_sys_read(fd, buf, sizeof(buf));
34 
35 		switch (n) {
36 		case 4:
37 			error = 0;
38 			goto out;
39 
40 		case -1:
41 			if (errno == ENXIO) {
42 				usleep(1000);
43 				continue;
44 			}
45 
46 			/* FALLTHROUGH */
47 		default:
48 			error = EPIPE;
49 			goto out;
50 		}
51 	}
52  out:
53 
54 	error = rump_daemonize_done(error);
55 	REQUIRE(error, "rump_daemonize_done");
56 
57 	if (error)
58 		exit(1);
59 
60 	return NULL;
61 }
62 
63 int
64 main(int argc, char *argv[])
65 {
66 	pthread_t pt;
67 	struct md_conf md;
68 	int fd, error;
69 
70 	if (argc != 2)
71 		exit(1);
72 
73 	md.md_addr = calloc(1, MDSIZE);
74 	md.md_size = MDSIZE;
75 	md.md_type = MD_UMEM_SERVER;
76 
77 	error = rump_daemonize_begin();
78 	REQUIRE(error, "rump_daemonize_begin");
79 
80 	error = rump_init();
81 	REQUIRE(error, "rump_init");
82 
83 	error = rump_init_server("unix://commsock");
84 	REQUIRE(error, "init server");
85 
86 	if ((fd = rump_sys_open(argv[1], O_RDWR)) == -1)
87 		err(1, "open");
88 
89 	/*
90 	 * Now, configuring the md driver also causes our process
91 	 * to start acting as the worker for the md.  Splitting it
92 	 * into two steps in the driver is not easy, since md is
93 	 * supposed to be unconfigured when the process dies
94 	 * (process may exit between calling ioctl1 and ioctl2).
95 	 * So, start a probe thread which attempts to read the md
96 	 * and declares the md as configured when the read is
97 	 * succesful.
98 	 */
99 	error = pthread_create(&pt, NULL, prober, argv[1]);
100 	REQUIRE(error, "pthread_create");
101 	pthread_detach(pt);
102 
103 	if (rump_sys_ioctl(fd, MD_SETCONF, &md) == -1) {
104 		rump_daemonize_done(errno);
105 		exit(1);
106 	}
107 
108 	return 0;
109 }
110