Module Name: src Committed By: pooka Date: Wed Oct 10 11:15:57 UTC 2012
Modified Files: src/lib/librumpuser: rumpuser.c Log Message: Implement the writewatchfile routines for a Linux hypervisor. As a result, the shmif network driver now works when hosted on Linux. To generate a diff of this commit: cvs rdiff -u -r1.20 -r1.21 src/lib/librumpuser/rumpuser.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/librumpuser/rumpuser.c diff -u src/lib/librumpuser/rumpuser.c:1.20 src/lib/librumpuser/rumpuser.c:1.21 --- src/lib/librumpuser/rumpuser.c:1.20 Fri Sep 14 16:29:22 2012 +++ src/lib/librumpuser/rumpuser.c Wed Oct 10 11:15:57 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser.c,v 1.20 2012/09/14 16:29:22 pooka Exp $ */ +/* $NetBSD: rumpuser.c,v 1.21 2012/10/10 11:15:57 pooka Exp $ */ /* * Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved. @@ -28,7 +28,7 @@ #include "rumpuser_port.h" #if !defined(lint) -__RCSID("$NetBSD: rumpuser.c,v 1.20 2012/09/14 16:29:22 pooka Exp $"); +__RCSID("$NetBSD: rumpuser.c,v 1.21 2012/10/10 11:15:57 pooka Exp $"); #endif /* !lint */ #include <sys/ioctl.h> @@ -572,7 +572,13 @@ rumpuser_seterrno(int error) errno = error; } -#ifdef __NetBSD__ +/* + * On NetBSD we use kqueue, on Linux we use inotify. The underlying + * interface requirements aren't quite the same, but we have a very + * good chance of doing the fd->path mapping on Linux thanks to dcache, + * so just keep the existing interfaces for now. + */ +#if defined(__NetBSD__) int rumpuser_writewatchfile_setup(int kq, int fd, intptr_t opaque, int *error) { @@ -615,6 +621,62 @@ rumpuser_writewatchfile_wait(int kq, int *opaque = kev.udata; return rv; } + +#elif defined(__linux__) +#include <sys/inotify.h> + +int +rumpuser_writewatchfile_setup(int inotify, int fd, intptr_t notused, int *error) +{ + char procbuf[PATH_MAX], linkbuf[PATH_MAX]; + ssize_t nn; + + if (inotify == -1) { + inotify = inotify_init(); + if (inotify == -1) { + seterror(errno); + return -1; + } + } + + /* ok, need to map fd into path for inotify */ + snprintf(procbuf, sizeof(procbuf), "/proc/self/fd/%d", fd); + nn = readlink(procbuf, linkbuf, sizeof(linkbuf)); + if (nn >= (ssize_t)sizeof(linkbuf)) { + nn = -1; + errno = E2BIG; /* pick something */ + } + if (nn == -1) { + seterror(errno); + close(inotify); + return -1; + } + + if (inotify_add_watch(inotify, linkbuf, IN_MODIFY) == -1) { + seterror(errno); + close(inotify); + return -1; + } + + return inotify; +} + +int +rumpuser_writewatchfile_wait(int kq, intptr_t *opaque, int *error) +{ + struct inotify_event iev; + ssize_t nn; + + do { + KLOCK_WRAP(nn = read(kq, &iev, sizeof(iev))); + } while (errno == EINTR); + + if (nn == -1) { + seterror(errno); + return -1; + } + return (nn/sizeof(iev)); +} #endif /*