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