xref: /netbsd/sys/rump/net/lib/libshmif/shmif_user.c (revision 2d75268c)
1*2d75268cSbad /*      $NetBSD: shmif_user.c,v 1.5 2019/03/26 08:56:17 bad Exp $	*/
2c0d3f0d5Spooka 
3c0d3f0d5Spooka /*-
4c0d3f0d5Spooka  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
5c0d3f0d5Spooka  *
6c0d3f0d5Spooka  * Redistribution and use in source and binary forms, with or without
7c0d3f0d5Spooka  * modification, are permitted provided that the following conditions
8c0d3f0d5Spooka  * are met:
9c0d3f0d5Spooka  * 1. Redistributions of source code must retain the above copyright
10c0d3f0d5Spooka  *    notice, this list of conditions and the following disclaimer.
11c0d3f0d5Spooka  * 2. Redistributions in binary form must reproduce the above copyright
12c0d3f0d5Spooka  *    notice, this list of conditions and the following disclaimer in the
13c0d3f0d5Spooka  *    documentation and/or other materials provided with the distribution.
14c0d3f0d5Spooka  *
15c0d3f0d5Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16c0d3f0d5Spooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17c0d3f0d5Spooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18c0d3f0d5Spooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c0d3f0d5Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c0d3f0d5Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21c0d3f0d5Spooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c0d3f0d5Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c0d3f0d5Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c0d3f0d5Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c0d3f0d5Spooka  * SUCH DAMAGE.
26c0d3f0d5Spooka  */
27eec3a080Salnsn 
28eec3a080Salnsn #include <sys/cdefs.h>
29*2d75268cSbad #ifdef __KERNEL_RCSID
30*2d75268cSbad __KERNEL_RCSID(0, "$NetBSD: shmif_user.c,v 1.5 2019/03/26 08:56:17 bad Exp $");
31*2d75268cSbad #endif
32eec3a080Salnsn 
33c0d3f0d5Spooka #ifndef _KERNEL
34c0d3f0d5Spooka #include <sys/types.h>
35c0d3f0d5Spooka #include <sys/mman.h>
36c0d3f0d5Spooka 
37c0d3f0d5Spooka #include <errno.h>
38933cb786Smartin #include <unistd.h>
39c0d3f0d5Spooka 
40c0d3f0d5Spooka #include <rump/rumpuser_component.h>
41c0d3f0d5Spooka 
42c0d3f0d5Spooka #include "shmif_user.h"
43c0d3f0d5Spooka 
44c0d3f0d5Spooka #define seterr(_v_) if ((_v_) == -1) *error = errno; else *error = 0;
45c0d3f0d5Spooka 
46c0d3f0d5Spooka /*
47c0d3f0d5Spooka  * On BSD we use kqueue, on Linux we use inotify.  The underlying
48c0d3f0d5Spooka  * interface requirements aren't quite the same, but we have a very
49c0d3f0d5Spooka  * good chance of doing the fd->path mapping on Linux thanks to dcache,
50c0d3f0d5Spooka  * so just keep the existing interfaces for now.
51c0d3f0d5Spooka  */
52c0d3f0d5Spooka #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) \
53c0d3f0d5Spooka     || defined(__OpenBSD__)
54c0d3f0d5Spooka #include <sys/event.h>
55c0d3f0d5Spooka 
56c0d3f0d5Spooka #include <stdlib.h>
57c0d3f0d5Spooka 
58c0d3f0d5Spooka int
rumpcomp_shmif_watchsetup(int * kqp,int fd)59c0d3f0d5Spooka rumpcomp_shmif_watchsetup(int *kqp, int fd)
60c0d3f0d5Spooka {
61c0d3f0d5Spooka 	struct kevent kev;
62c0d3f0d5Spooka 	int rv, kq;
63c0d3f0d5Spooka 
64c0d3f0d5Spooka 	kq = *kqp;
65c0d3f0d5Spooka 	if (kq == -1) {
66c0d3f0d5Spooka 		kq = kqueue();
67c0d3f0d5Spooka 		if (kq == -1) {
68c0d3f0d5Spooka 			rv = errno;
69c0d3f0d5Spooka 			goto out;
70c0d3f0d5Spooka 		}
71c0d3f0d5Spooka 	}
72c0d3f0d5Spooka 
73c0d3f0d5Spooka 	EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR,
74c0d3f0d5Spooka 	    NOTE_WRITE, 0, 0);
75c0d3f0d5Spooka 	if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) {
76c0d3f0d5Spooka 		rv = errno;
77c0d3f0d5Spooka 	} else {
78c0d3f0d5Spooka 		rv = 0;
79c0d3f0d5Spooka 		*kqp = kq;
80c0d3f0d5Spooka 	}
81c0d3f0d5Spooka 
82c0d3f0d5Spooka  out:
83c0d3f0d5Spooka 	return rumpuser_component_errtrans(rv);
84c0d3f0d5Spooka }
85c0d3f0d5Spooka 
86c0d3f0d5Spooka int
rumpcomp_shmif_watchwait(int kq)87c0d3f0d5Spooka rumpcomp_shmif_watchwait(int kq)
88c0d3f0d5Spooka {
89c0d3f0d5Spooka 	void *cookie;
90c0d3f0d5Spooka 	struct kevent kev;
91c0d3f0d5Spooka 	int rv;
92c0d3f0d5Spooka 
93c0d3f0d5Spooka 	cookie = rumpuser_component_unschedule();
94c0d3f0d5Spooka 	do {
95c0d3f0d5Spooka 		rv = kevent(kq, NULL, 0, &kev, 1, NULL);
96c0d3f0d5Spooka 	} while (rv == -1 && errno == EINTR);
97c0d3f0d5Spooka 	if (rv == -1) {
98c0d3f0d5Spooka 		rv = errno;
99c0d3f0d5Spooka 	} else {
100c0d3f0d5Spooka 		rv = 0;
101c0d3f0d5Spooka 	}
102c0d3f0d5Spooka 	rumpuser_component_schedule(cookie);
103c0d3f0d5Spooka 
104c0d3f0d5Spooka 	return rumpuser_component_errtrans(rv);
105c0d3f0d5Spooka }
106c0d3f0d5Spooka 
107c0d3f0d5Spooka #elif defined(__linux__)
108c0d3f0d5Spooka #include <sys/inotify.h>
109c0d3f0d5Spooka 
110c0d3f0d5Spooka #include <limits.h>
111c0d3f0d5Spooka #include <stdio.h>
112c0d3f0d5Spooka 
113c0d3f0d5Spooka int
rumpcomp_shmif_watchsetup(int * inotifyp,int fd)114c0d3f0d5Spooka rumpcomp_shmif_watchsetup(int *inotifyp, int fd)
115c0d3f0d5Spooka {
116c0d3f0d5Spooka 	char procbuf[PATH_MAX], linkbuf[PATH_MAX];
117c0d3f0d5Spooka 	ssize_t nn;
118c0d3f0d5Spooka 	int inotify, rv;
119c0d3f0d5Spooka 
120c0d3f0d5Spooka 	inotify = *inotifyp;
121c0d3f0d5Spooka 	if (inotify == -1) {
122c0d3f0d5Spooka 		inotify = inotify_init();
123c0d3f0d5Spooka 		if (inotify == -1) {
124c0d3f0d5Spooka 			rv = errno;
125c0d3f0d5Spooka 			goto out;
126c0d3f0d5Spooka 		}
127c0d3f0d5Spooka 	}
128c0d3f0d5Spooka 
129c0d3f0d5Spooka 	/* ok, need to map fd into path for inotify */
130c0d3f0d5Spooka 	snprintf(procbuf, sizeof(procbuf), "/proc/self/fd/%d", fd);
131c0d3f0d5Spooka 	nn = readlink(procbuf, linkbuf, sizeof(linkbuf)-1);
132c0d3f0d5Spooka 	if (nn >= (ssize_t)sizeof(linkbuf)-1) {
133c0d3f0d5Spooka 		nn = -1;
134c0d3f0d5Spooka 		errno = E2BIG; /* pick something */
135c0d3f0d5Spooka 	}
136c0d3f0d5Spooka 	if (nn == -1) {
137c0d3f0d5Spooka 		rv = errno;
138c0d3f0d5Spooka 		close(inotify);
139c0d3f0d5Spooka 		goto out;
140c0d3f0d5Spooka 	}
141c0d3f0d5Spooka 
142c0d3f0d5Spooka 	linkbuf[nn] = '\0';
143c0d3f0d5Spooka 	if (inotify_add_watch(inotify, linkbuf, IN_MODIFY) == -1) {
144c0d3f0d5Spooka 		rv = errno;
145c0d3f0d5Spooka 		close(inotify);
146c0d3f0d5Spooka 		goto out;
147c0d3f0d5Spooka 	}
148c0d3f0d5Spooka 	rv = 0;
149c0d3f0d5Spooka 	*inotifyp = inotify;
150c0d3f0d5Spooka 
151c0d3f0d5Spooka  out:
152c0d3f0d5Spooka 	return rumpuser_component_errtrans(rv);
153c0d3f0d5Spooka }
154c0d3f0d5Spooka 
155c0d3f0d5Spooka int
rumpcomp_shmif_watchwait(int kq)156c0d3f0d5Spooka rumpcomp_shmif_watchwait(int kq)
157c0d3f0d5Spooka {
158c0d3f0d5Spooka 	struct inotify_event iev;
159c0d3f0d5Spooka 	void *cookie;
160c0d3f0d5Spooka 	ssize_t nn;
161c0d3f0d5Spooka 	int rv;
162c0d3f0d5Spooka 
163c0d3f0d5Spooka 	cookie = rumpuser_component_unschedule();
164c0d3f0d5Spooka 	do {
165c0d3f0d5Spooka 		nn = read(kq, &iev, sizeof(iev));
166c0d3f0d5Spooka 	} while (nn == -1 && errno == EINTR);
167c0d3f0d5Spooka 	if (nn == -1) {
168c0d3f0d5Spooka 		rv = errno;
169c0d3f0d5Spooka 	} else {
170c0d3f0d5Spooka 		rv = 0;
171c0d3f0d5Spooka 	}
172c0d3f0d5Spooka 
173c0d3f0d5Spooka 	rumpuser_component_schedule(cookie);
174c0d3f0d5Spooka 
175c0d3f0d5Spooka 	return rumpuser_component_errtrans(rv);
176c0d3f0d5Spooka }
177c0d3f0d5Spooka 
178c0d3f0d5Spooka #else
179c0d3f0d5Spooka #include <stdio.h>
180c0d3f0d5Spooka 
181c0d3f0d5Spooka /* a polling default implementation */
182c0d3f0d5Spooka int
rumpcomp_shmif_watchsetup(int * nono,int fd)183c0d3f0d5Spooka rumpcomp_shmif_watchsetup(int *nono, int fd)
184c0d3f0d5Spooka {
185c0d3f0d5Spooka 	static int warned = 0;
186c0d3f0d5Spooka 
187c0d3f0d5Spooka 	if (!warned) {
188c0d3f0d5Spooka 		fprintf(stderr, "WARNING: rumpuser writewatchfile routines are "
189c0d3f0d5Spooka 		    "polling-only on this platform\n");
190c0d3f0d5Spooka 		warned = 1;
191c0d3f0d5Spooka 	}
192c0d3f0d5Spooka 
193c0d3f0d5Spooka 	return 0;
194c0d3f0d5Spooka }
195c0d3f0d5Spooka 
196c0d3f0d5Spooka int
rumpcomp_shmif_watchwait(int kq)197c0d3f0d5Spooka rumpcomp_shmif_watchwait(int kq)
198c0d3f0d5Spooka {
199c0d3f0d5Spooka 	void *cookie;
200c0d3f0d5Spooka 
201c0d3f0d5Spooka 	cookie = rumpuser_component_unschedule();
202c0d3f0d5Spooka 	usleep(10000);
203c0d3f0d5Spooka 	rumpuser_component_schedule(cookie);
204c0d3f0d5Spooka 
205c0d3f0d5Spooka 	return 0;
206c0d3f0d5Spooka }
207c0d3f0d5Spooka #endif
208c0d3f0d5Spooka 
209c0d3f0d5Spooka int
rumpcomp_shmif_mmap(int fd,size_t len,void ** memp)210c0d3f0d5Spooka rumpcomp_shmif_mmap(int fd, size_t len, void **memp)
211c0d3f0d5Spooka {
212c0d3f0d5Spooka 	void *mem;
213c0d3f0d5Spooka 	int rv;
214c0d3f0d5Spooka 
215c0d3f0d5Spooka 	if (ftruncate(fd, len) == -1) {
216c0d3f0d5Spooka 		rv = errno;
217c0d3f0d5Spooka 		goto out;
218c0d3f0d5Spooka 	}
219c0d3f0d5Spooka 
220c0d3f0d5Spooka #if defined(__sun__) && !defined(MAP_FILE)
221c0d3f0d5Spooka #define MAP_FILE 0
222c0d3f0d5Spooka #endif
223c0d3f0d5Spooka 
224c0d3f0d5Spooka 	mem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
225c0d3f0d5Spooka 	if (mem == MAP_FAILED) {
226c0d3f0d5Spooka 		rv = errno;
227c0d3f0d5Spooka 	} else {
228c0d3f0d5Spooka 		rv = 0;
229c0d3f0d5Spooka 		*memp = mem;
230c0d3f0d5Spooka 	}
231c0d3f0d5Spooka 
232c0d3f0d5Spooka  out:
233c0d3f0d5Spooka 	return rumpuser_component_errtrans(rv);
234c0d3f0d5Spooka }
235c0d3f0d5Spooka #endif
236