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