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
 
 /*

Reply via email to