Module Name:    src
Committed By:   manu
Date:           Wed Sep 15 01:51:44 UTC 2010

Modified Files:
        src/lib/libperfuse: debug.c fuse.h ops.c perfuse.c perfuse_if.h
            perfuse_priv.h
        src/usr.sbin/perfused: debug.c msg.c perfused.c perfused.h

Log Message:
- Use SOCK_DGRAM instead of SOCK_STREAM, as the filesystem seems to
assume datagram semantics: when using SOCK_STREAM, if perfused sends
frames faster than the filesystem consumes them, it will grab multiple
frames at once and discard anything beyond the first one. For now the
code can work both with SOCK_DGRAM and SOCK_STREAM, but SOCK_STREAM
support will probably have to be removed for the sake of readability.

- Remeber to sync parent directories when moving a node

- In debug output, display the requeue type (readdir, write, etc...)


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/lib/libperfuse/debug.c src/lib/libperfuse/fuse.h
cvs rdiff -u -r1.14 -r1.15 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.5 -r1.6 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.7 -r1.8 src/lib/libperfuse/perfuse_if.h
cvs rdiff -u -r1.9 -r1.10 src/lib/libperfuse/perfuse_priv.h
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/perfused/debug.c \
    src/usr.sbin/perfused/perfused.h
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/perfused/msg.c
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/perfused/perfused.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/libperfuse/debug.c
diff -u src/lib/libperfuse/debug.c:1.1 src/lib/libperfuse/debug.c:1.2
--- src/lib/libperfuse/debug.c:1.1	Wed Aug 25 07:16:00 2010
+++ src/lib/libperfuse/debug.c	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: debug.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */
+/*  $NetBSD: debug.c,v 1.2 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -79,6 +79,8 @@
 	{ 0, "UNKNOWN" },
 };
 
+const char *perfuse_qtypestr[] = { "READDIR", "READ", "WRITE", "AFTERWRITE" };
+
 const char *
 perfuse_opname(opcode)
 	int opcode;
Index: src/lib/libperfuse/fuse.h
diff -u src/lib/libperfuse/fuse.h:1.1 src/lib/libperfuse/fuse.h:1.2
--- src/lib/libperfuse/fuse.h:1.1	Wed Aug 25 07:16:00 2010
+++ src/lib/libperfuse/fuse.h	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: fuse.h,v 1.1 2010/08/25 07:16:00 manu Exp $ */
+/*  $NetBSD: fuse.h,v 1.2 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -33,9 +33,11 @@
 #define FUSE_ROOT_ID 1
 #define FUSE_UNKNOWN_FH (uint64_t)0
 
+#ifndef FUSE_BUFSIZE
 #define FUSE_MIN_BUFSIZE 0x21000
 #define FUSE_PREF_BUFSIZE (PAGE_SIZE + 0x1000)
-#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE, FUSE_MIN_BUFSIZE)
+#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE /* CONSTCOND */, FUSE_MIN_BUFSIZE)
+#endif /* FUSE_BUFSIZE */
 
 struct fuse_attr {
 	uint64_t	ino;

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.14 src/lib/libperfuse/ops.c:1.15
--- src/lib/libperfuse/ops.c:1.14	Thu Sep  9 09:12:35 2010
+++ src/lib/libperfuse/ops.c	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.14 2010/09/09 09:12:35 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.15 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -613,10 +613,10 @@
 	TAILQ_INSERT_TAIL(&pnd->pnd_pcq, &pcq, pcq_next);
 
 #ifdef PERFUSE_DEBUG
-
 	if (perfuse_diagflags & PDF_REQUEUE)
-		DPRINTF("%s: REQUEUE opc = %p, pcc = %p\n", 
-		       __func__, (void *)opc, pcq.pcq_cc);
+		DPRINTF("%s: REQUEUE opc = %p, pcc = %p (%s)\n", 
+		        __func__, (void *)opc, pcq.pcq_cc,
+			perfuse_qtypestr[type]);
 #endif
 
 	puffs_cc_yield(pcq.pcq_cc);
@@ -624,8 +624,9 @@
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_REQUEUE)
-		DPRINTF("%s: RESUME opc = %p, pcc = %p\n",
-		        __func__, (void *)opc, pcq.pcq_cc);
+		DPRINTF("%s: RESUME opc = %p, pcc = %p (%s)\n",
+		        __func__, (void *)opc, pcq.pcq_cc,
+			perfuse_qtypestr[type]);
 #endif
 
 	return;
@@ -654,8 +655,9 @@
 	
 #ifdef PERFUSE_DEBUG
 		if (perfuse_diagflags & PDF_REQUEUE)
-			DPRINTF("%s: SCHEDULE opc = %p, pcc = %p\n",
-				__func__, (void *)opc, pcq->pcq_cc);
+			DPRINTF("%s: SCHEDULE opc = %p, pcc = %p (%s)\n",
+				__func__, (void *)opc, pcq->pcq_cc,
+				 perfuse_qtypestr[type]);
 #endif
 		puffs_cc_schedule(pcq->pcq_cc);
 		
@@ -1812,11 +1814,15 @@
 	/*
 	 * Update source and destination directories child count
 	 * Update moved object parent directory
+	 * Set dirty flag for source and parent
 	 */
 	PERFUSE_NODE_DATA(opc)->pnd_childcount--;
 	PERFUSE_NODE_DATA(targ_dir)->pnd_childcount++;
+
 	PERFUSE_NODE_DATA(src)->pnd_parent = targ_dir;
 
+	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
+	PERFUSE_NODE_DATA(targ_dir)->pnd_flags |= PND_DIRTY;
 out:
 	ps->ps_destroy_msg(pm);
 
@@ -2219,13 +2225,14 @@
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_RECLAIM)
 		DPRINTF("%s (nodeid %"PRId64") is %sreclaimed, "
-			"has childcount %d %s%s%s, pending ops:%s%s\n", 
+			"has childcount %d %s%s%s, pending ops:%s%s%s\n", 
 		        (char *)PNPATH(pn), pnd->pnd_ino,
 		        pnd->pnd_flags & PND_RECLAIMED ? "" : "not ",
 		        pnd->pnd_childcount,
 			pnd->pnd_flags & PND_OPEN ? "open " : "not open",
 			pnd->pnd_flags & PND_RFH ? "r" : "",
 			pnd->pnd_flags & PND_WFH ? "w" : "",
+			pnd->pnd_flags & PND_BUSY ? "" : " none",
 			pnd->pnd_flags & PND_INREADDIR ? " readdir" : "",
 			pnd->pnd_flags & PND_INWRITE ? " write" : "");
 #endif

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.5 src/lib/libperfuse/perfuse.c:1.6
--- src/lib/libperfuse/perfuse.c:1.5	Tue Sep  7 02:11:04 2010
+++ src/lib/libperfuse/perfuse.c	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.5 2010/09/07 02:11:04 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.6 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <machine/vmparam.h>
 
 #define LIBPERFUSE
 #include "perfuse.h"
@@ -109,17 +110,30 @@
 	char fdstr[16];
 	char *const argv[] = { progname, minus_i, fdstr, NULL};
 	char *const envp[] = { NULL };
+	uint32_t opt;
 
 	if (strcmp(path, _PATH_FUSE) != 0)
 		return open(path, flags, mode);
 
-	if ((sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
+	if ((sv[0] = socket(PF_LOCAL, PERFUSE_SOCKTYPE, 0)) == -1) {
 #ifdef PERFUSE_DEBUG
 		DWARN("%s:%d socket failed: %s", __func__, __LINE__);
 #endif
 		return -1;
 	}
 
+	/*
+	 * Set a buffer lentgh large enough so that any FUSE packet
+	 * will fit.
+	 */
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
+
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
+
 	sa = (struct sockaddr *)(void *)&sun;
 	sun.sun_len = sizeof(sun);
 	sun.sun_family = AF_LOCAL;
@@ -135,13 +149,39 @@
 	 * we will talk using a socketpair 
 	 * instead of /dev/fuse.
 	 */
-	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) != 0) {
-#ifdef PERFUSE_DEBUG
+	if (socketpair(PF_LOCAL, PERFUSE_SOCKTYPE, 0, sv) != 0) {
 		DWARN("%s:%d: socketpair failed", __func__, __LINE__);
-#endif
 		return -1;
 	}
 
+	/*
+	 * Set a buffer lentgh large enough so that any FUSE packet
+	 * will fit.
+	 */
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
+
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
+
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
+
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
+
+	/*
+	 * Request peer credentials. This musr be done before first 
+	 * frame is sent.
+	 */
+	opt = 1;
+	if (setsockopt(sv[1], 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt LOCAL_CREDS failed", __func__);
+
 	(void)sprintf(fdstr, "%d", sv[1]);
 
 	switch(fork()) {
@@ -167,7 +207,6 @@
 	return sv[0];
 }
 
-
 int
 perfuse_mount(source, target, filesystemtype, mountflags, data)
 	const char *source;
@@ -178,7 +217,16 @@
 {
 	int s;
 	size_t len;
-	struct perfuse_mount_out pmo;
+	struct perfuse_mount_out *pmo;
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+	struct sockaddr_storage ss;
+	struct sockaddr_un sun;
+	struct sockaddr *sa;
+	socklen_t sa_len;
+#endif
+	size_t sock_len;
+	char *frame;
+	char *cp;
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_MISC)
@@ -189,70 +237,95 @@
 
 	if ((s = get_fd(data)) == -1)
 		return -1;
-	
-	pmo.pmo_len = sizeof(pmo);
-	pmo.pmo_len += source ? (uint32_t)strlen(source) : 0;
-	pmo.pmo_len += target ? (uint32_t)strlen(target) : 0;
-	pmo.pmo_len += filesystemtype ? (uint32_t)strlen(filesystemtype) : 0;
-	pmo.pmo_len += data ? (uint32_t)strlen(data) : 0;
-	pmo.pmo_error = 0;
-	pmo.pmo_unique = (uint64_t)-1;
-
-	(void)strcpy(pmo.pmo_magic, PERFUSE_MOUNT_MAGIC);
-	pmo.pmo_source_len = source ? (uint32_t)strlen(source) : 0;
-	pmo.pmo_target_len = target ? (uint32_t)strlen(target) : 0;
-	pmo.pmo_filesystemtype_len = 
-	    filesystemtype ? (uint32_t)strlen(filesystemtype) : 0;
-	pmo.pmo_mountflags = (uint32_t)mountflags;
-	pmo.pmo_data_len = data ? (uint32_t)strlen(data) : 0;
-	
 
-	if (write(s, &pmo, sizeof(pmo)) != sizeof(pmo)) {
+	/*
+	 * If we are connected to /dev/fuse, we need a second
+	 * socket to get replies from perfused.
+	 * XXX This socket is not removed at exit time yet
+	 */
+	sock_len = 0;
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+	sa = (struct sockaddr *)(void *)&ss;
+	sa_len = sizeof(ss);
+	if ((getpeername(s, sa, &sa_len) == 0) &&
+	    (sa->sa_family = AF_LOCAL) &&
+	    (strcmp(((struct sockaddr_un *)sa)->sun_path, _PATH_FUSE) == 0)) {
+
+		sa = (struct sockaddr *)(void *)&sun;
+		sun.sun_len = sizeof(sun);
+		sun.sun_family = AF_LOCAL;
+		(void)sprintf(sun.sun_path, "%s/%s-%d",
+			      _PATH_TMP, getprogname(), getpid());
+		
+		if (bind(s, sa, sa->sa_len) != 0)
+			DERR(EX_OSERR, "%s:%d bind to \"%s\" failed",
+			     __func__, __LINE__, sun.sun_path);
+
+		sock_len = strlen(sun.sun_path) + 1;
+	}
+#endif /* PERFUSE_SOCKTYPE */
+		
+	len = sizeof(*pmo);
+	len += source ? (uint32_t)strlen(source) + 1 : 0;
+	len += target ? (uint32_t)strlen(target) + 1 : 0;
+	len += filesystemtype ? (uint32_t)strlen(filesystemtype) + 1 : 0;
+	len += data ? (uint32_t)strlen(data) + 1 : 0;
+	len += sock_len;
+
+	if ((frame = malloc(len)) == NULL) {
 #ifdef PERFUSE_DEBUG
 		if (perfuse_diagflags & PDF_MISC)
-			DPRINTF("%s:%d short write\n", __func__, __LINE__);
+			DWARN("%s:%d malloc failed", __func__, __LINE__);
 #endif
 		return -1;
 	}
+
+	pmo = (struct perfuse_mount_out *)(void *)frame;
+	pmo->pmo_len = len;
+	pmo->pmo_error = 0;
+	pmo->pmo_unique = (uint64_t)-1;
+	(void)strcpy(pmo->pmo_magic, PERFUSE_MOUNT_MAGIC);
+
+	pmo->pmo_source_len = source ? (uint32_t)strlen(source) + 1 : 0;
+	pmo->pmo_target_len = target ? (uint32_t)strlen(target) + 1: 0;
+	pmo->pmo_filesystemtype_len = 
+	    filesystemtype ? (uint32_t)strlen(filesystemtype) + 1 : 0;
+	pmo->pmo_mountflags = (uint32_t)mountflags;
+	pmo->pmo_data_len = data ? (uint32_t)strlen(data) + 1 : 0;
+	pmo->pmo_sock_len = sock_len;
 	
+	cp = (char *)(void *)(pmo + 1);
+
 	if (source) {
-		len = pmo.pmo_source_len;
-		if (write(s, source, len) != (ssize_t)len) {
-#ifdef PERFUSE_DEBUG
-			DWARNX("%s:%d short write\n", __func__, __LINE__);
-#endif
-			return -1;
-		}
+		(void)strcpy(cp, source);
+		cp += pmo->pmo_source_len;
 	}
 	
 	if (target) {
-		len = pmo.pmo_target_len;
-		if (write(s, target, len) != (ssize_t)len) {
-#ifdef PERFUSE_DEBUG
-			DWARNX("%s:%d short write\n", __func__, __LINE__);
-#endif
-			return -1;
-		}
+		(void)strcpy(cp, target);
+		cp += pmo->pmo_target_len;
 	}
-	
+
 	if (filesystemtype) {
-		len = pmo.pmo_filesystemtype_len;
-		if (write(s, filesystemtype, len) != (ssize_t)len) {
-#ifdef PERFUSE_DEBUG
-			DWARNX("%s:%d short write\n", __func__, __LINE__);
-#endif
-			return -1;
-		}
+		(void)strcpy(cp, filesystemtype);
+		cp += pmo->pmo_filesystemtype_len;
 	}
 	
 	if (data) {
-		len = pmo.pmo_data_len;
-		if (write(s, data, len) != (ssize_t)len) {
+		(void)strcpy(cp, data);
+		cp += pmo->pmo_data_len;
+	}
+
+	if (sock_len != 0) {
+		(void)strcpy(cp, sun.sun_path);
+		cp += pmo->pmo_sock_len;
+	}
+
+	if (send(s, frame, len, MSG_NOSIGNAL) != len) {
 #ifdef PERFUSE_DEBUG
-			DWARNX("%s:%d short write\n", __func__, __LINE__);
+		DWARN("%s:%d sendto failed", __func__, __LINE__);
 #endif
-			return -1;
-		}
+		return -1;
 	}
 
 	return 0;

Index: src/lib/libperfuse/perfuse_if.h
diff -u src/lib/libperfuse/perfuse_if.h:1.7 src/lib/libperfuse/perfuse_if.h:1.8
--- src/lib/libperfuse/perfuse_if.h:1.7	Tue Sep  7 02:11:04 2010
+++ src/lib/libperfuse/perfuse_if.h	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_if.h,v 1.7 2010/09/07 02:11:04 manu Exp $ */
+/*  $NetBSD: perfuse_if.h,v 1.8 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -36,6 +36,7 @@
 #define PERFUSE_MOUNT_MAGIC "noFuseRq"
 #define PERFUSE_UNKNOWN_INO 0xffffffff
 
+#define PERFUSE_SOCKTYPE SOCK_DGRAM
 /* 
  * Diagnostic flags. This global is used only for DPRINTF/DERR/DWARN
  */
@@ -157,6 +158,7 @@
 	uint32_t pmo_filesystemtype_len;
 	uint32_t pmo_mountflags;
 	uint32_t pmo_data_len;
+	uint32_t pmo_sock_len;
 };
 
 struct perfuse_mount_info {
@@ -171,9 +173,11 @@
 /*
  * Duplicated fro fuse.h to avoid making it public
  */
+#ifndef FUSE_BUFSIZE
 #define FUSE_MIN_BUFSIZE 0x21000
 #define FUSE_PREF_BUFSIZE (PAGE_SIZE + 0x1000)
-#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE, FUSE_MIN_BUFSIZE)
+#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE /* CONSTCOND */, FUSE_MIN_BUFSIZE)
+#endif /* FUSE_BUFSIZE */
 
 struct fuse_in_header {
 	uint32_t	len;

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.9 src/lib/libperfuse/perfuse_priv.h:1.10
--- src/lib/libperfuse/perfuse_priv.h:1.9	Thu Sep  9 09:12:35 2010
+++ src/lib/libperfuse/perfuse_priv.h	Wed Sep 15 01:51:43 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.9 2010/09/09 09:12:35 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.10 2010/09/15 01:51:43 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -71,6 +71,9 @@
 
 
 enum perfuse_qtype { PCQ_READDIR, PCQ_READ, PCQ_WRITE, PCQ_AFTERWRITE };
+#ifdef PERFUSE_DEBUG
+extern const char *perfuse_qtypestr[];
+#endif
 
 struct perfuse_cc_queue {
 	enum perfuse_qtype pcq_type;
@@ -101,6 +104,7 @@
 #define PND_INWRITE		0x40	/* write in progress */
 
 #define PND_OPEN		(PND_RFH|PND_WFH)	/* File is open */
+#define PND_BUSY		(PND_INREADDIR|PND_INWRITE)
 	puffs_cookie_t pnd_parent;
 	int pnd_childcount;
 };

Index: src/usr.sbin/perfused/debug.c
diff -u src/usr.sbin/perfused/debug.c:1.2 src/usr.sbin/perfused/debug.c:1.3
--- src/usr.sbin/perfused/debug.c:1.2	Thu Aug 26 13:29:02 2010
+++ src/usr.sbin/perfused/debug.c	Wed Sep 15 01:51:44 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: debug.c,v 1.2 2010/08/26 13:29:02 manu Exp $ */
+/*  $NetBSD: debug.c,v 1.3 2010/09/15 01:51:44 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <syslog.h>
 #include <ctype.h>
+#include <sys/socket.h>
 
 #include "perfused.h"
 
Index: src/usr.sbin/perfused/perfused.h
diff -u src/usr.sbin/perfused/perfused.h:1.2 src/usr.sbin/perfused/perfused.h:1.3
--- src/usr.sbin/perfused/perfused.h:1.2	Fri Aug 27 09:58:17 2010
+++ src/usr.sbin/perfused/perfused.h	Wed Sep 15 01:51:44 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfused.h,v 1.2 2010/08/27 09:58:17 manu Exp $ */
+/*  $NetBSD: perfused.h,v 1.3 2010/09/15 01:51:44 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -43,8 +43,7 @@
 #endif /* PERFUSE_DEBUG */
 
 int perfuse_open_sock(void);
-void *perfuse_recv_early(int, size_t);
-
+void *perfuse_recv_early(int, struct sockcred *, size_t); 
 int perfuse_readframe(struct puffs_usermount *, 
      struct puffs_framebuf *, int, int *);
 int perfuse_writeframe(struct puffs_usermount *, 

Index: src/usr.sbin/perfused/msg.c
diff -u src/usr.sbin/perfused/msg.c:1.5 src/usr.sbin/perfused/msg.c:1.6
--- src/usr.sbin/perfused/msg.c:1.5	Tue Sep  7 02:11:04 2010
+++ src/usr.sbin/perfused/msg.c	Wed Sep 15 01:51:44 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: msg.c,v 1.5 2010/09/07 02:11:04 manu Exp $ */
+/*  $NetBSD: msg.c,v 1.6 2010/09/15 01:51:44 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -35,6 +35,8 @@
 #include <syslog.h>
 #include <paths.h>
 #include <puffs.h>
+#include <limits.h>
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <machine/vmparam.h>
@@ -53,46 +55,106 @@
 	int s;
 	struct sockaddr_un sun;
 	const struct sockaddr *sa;
+	uint32_t opt;
 
 	(void)unlink(_PATH_FUSE);
 
-	if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1)
+	if ((s = socket(AF_LOCAL, PERFUSE_SOCKTYPE, 0)) == -1)
 		err(EX_OSERR, "socket failed");
 
 	sa = (const struct sockaddr *)(void *)&sun;
 	sun.sun_len = sizeof(sun);
 	sun.sun_family = AF_LOCAL;
 	(void)strcpy(sun.sun_path, _PATH_FUSE); 
+
+	/*
+	 * Set a buffer lentgh large enough so that any FUSE packet
+	 * will fit.
+	 */
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
+
+	opt = FUSE_BUFSIZE;
+	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
+
+	/*
+	 * Request peer credentials
+	 */
+	opt = 1;
+	if (setsockopt(s, 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0)
+		DWARN("%s: setsockopt LOCAL_CREDS failed", __func__);
 	
 	if (bind(s, sa, (socklen_t )sun.sun_len) == -1)
 		err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
 
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+	if (connect(s, sa, (socklen_t )sun.sun_len) == -1)
+		err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
+#else
 	if (listen(s, 1) == -1)	
 		err(EX_OSERR, "listen failed");
+#endif
 
 	return s;
 }
 
 
 void *
-perfuse_recv_early(fd, len)
+perfuse_recv_early(fd, sockcred, sockcred_len)
 	int fd;
-	size_t len;
+	struct sockcred *sockcred;
+	size_t sockcred_len;
 {
+	struct fuse_out_header foh;
+	size_t len;
 	char *buf;
+	struct msghdr msg;
+	char cmsg_buf[sizeof(struct cmsghdr) + SOCKCREDSIZE(NGROUPS_MAX)];
+	struct cmsghdr *cmsg = (struct cmsghdr *)(void *)&cmsg_buf;
+	struct sockcred *sc = (struct sockcred *)(void *)(cmsg + 1);
+	struct iovec iov;
+	
+	len = sizeof(foh);
+
+	/*
+	 * We use the complicated recvmsg because we want peer creds.
+	 */
+	iov.iov_base = &foh;
+	iov.iov_len = len;
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = cmsg;
+	msg.msg_controllen = sizeof(cmsg_buf);
+	msg.msg_flags = 0;
 
-	if (len == 0)
+	if (recvmsg(fd, &msg, MSG_NOSIGNAL|MSG_PEEK) != (ssize_t)len) {
+		DWARN("short recv (header)");
 		return NULL;
+	}
+
+	if (cmsg->cmsg_type != SCM_CREDS) {
+		DWARNX("No SCM_CREDS");
+		return NULL;
+	}
+
+	if (sockcred != NULL)
+		(void)memcpy(sockcred, sc,
+			     MIN(cmsg->cmsg_len - sizeof(*cmsg), sockcred_len));
+		
 
-	if ((buf = malloc(len + 1)) == NULL)
+	len = foh.len;
+	if ((buf = malloc(len)) == NULL)
 		err(EX_OSERR, "malloc(%zd) failed", len);
 
-	if (read(fd, buf, len) != (ssize_t)len) {
-		DWARN("short read");
+	if (recv(fd, buf, len, MSG_NOSIGNAL) != (ssize_t)len) {
+		DWARN("short recv (frame)");
 		return NULL;
 	}
 
-	buf[len] = '\0';
 	return buf;
 }
 
@@ -416,17 +478,24 @@
 	size_t remain;
 	ssize_t readen;
 	void *data;
+	int peek = 0;
+
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+	peek = MSG_PEEK;
+#endif
 
 	offset = puffs_framebuf_telloff(pufbuf);
 
 	/*
 	 * Read the header 
+	 * MSG_PEEK is used so that this code works for SOCK_DGRAM
+	 * socket. The loop is only needed to work with SOCK_STREAM. 
 	 */
 	while (offset < sizeof(foh)) {
 		remain = sizeof(foh) - offset;
 		PUFFS_FRAMEBUF_GETWINDOW(pufbuf, offset, &data, &remain);
 
-		switch (readen = recv(fd, data, remain, MSG_NOSIGNAL)) {
+		switch (readen = recv(fd, data, remain, MSG_NOSIGNAL|peek)) {
 		case 0:
 			DWARNX("%s: recv retunred 0", __func__);
 			return ECONNRESET;
@@ -448,6 +517,12 @@
 			DERR(EX_OSERR, "puffs_framebuf_seekset failed");
 	}
 
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+	/*
+	 * We had a peek at the header, now really read it.
+	 */
+	offset = 0;
+#endif
 	
 	/*
 	 * We have a header, get remaing length to read

Index: src/usr.sbin/perfused/perfused.c
diff -u src/usr.sbin/perfused/perfused.c:1.7 src/usr.sbin/perfused/perfused.c:1.8
--- src/usr.sbin/perfused/perfused.c:1.7	Tue Sep  7 02:11:04 2010
+++ src/usr.sbin/perfused/perfused.c	Wed Sep 15 01:51:44 2010
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfused.c,v 1.7 2010/09/07 02:11:04 manu Exp $ */
+/*  $NetBSD: perfused.c,v 1.8 2010/09/15 01:51:44 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -50,7 +50,6 @@
 #include "../../lib/libperfuse/perfuse_if.h"
 #include "perfused.h"
 
-static int getpeerid(int, pid_t *, uid_t *, gid_t *);
 static int access_mount(const char *, uid_t, int);
 static void new_mount(int, int);
 static int parse_debug(char *);
@@ -67,34 +66,6 @@
 
 
 static int
-getpeerid(s, pidp, uidp, gidp)
-	int s;
-	pid_t *pidp;
-	uid_t *uidp;
-	gid_t *gidp;
-{
-	struct unpcbid unp;
-	socklen_t len;
-	int error;
-
-	len = sizeof(unp);
-	error = getsockopt(s, 0, LOCAL_PEEREID, &unp, &len);
-	if (error != 0)
-		return error;
-		
-	if (pidp != NULL)
-		*pidp = unp.unp_pid;
-
-	if (uidp != NULL)
-		*uidp = unp.unp_euid;
-
-	if (gidp != NULL)
-		*gidp = unp.unp_egid;
-
-	return 0;
-}
-
-static int
 access_mount(mnt, uid, ro)
 	const char *mnt;
 	uid_t uid;
@@ -128,14 +99,18 @@
 	struct perfuse_mount_info *pmi;
 {
 	struct perfuse_mount_out *pmo;
+	struct sockcred cred;
+	char *cp;
 	char *source = NULL;
 	char *target = NULL;
 	char *filesystemtype = NULL;
 	long mountflags = 0;
-	void *data;
-	size_t len;
+	void *data = NULL;
+	char *sock = NULL;
+
+	pmo = (struct perfuse_mount_out *)
+		perfuse_recv_early(fd, &cred, sizeof(cred));
 
-	pmo = (struct perfuse_mount_out *)perfuse_recv_early(fd, sizeof(*pmo));
 	if (pmo == NULL) {
 		if (shutdown(fd, SHUT_RDWR) != 0)
 			DERR(EX_OSERR, "shutdown failed");
@@ -146,29 +121,45 @@
 	if (perfuse_diagflags & PDF_MISC)
 		DPRINTF("perfuse lengths: source = %"PRId32", "
 			"target = %"PRId32", filesystemtype = %"PRId32", "
-			"data = %"PRId32"\n", pmo->pmo_source_len, 
-			pmo->pmo_target_len, pmo->pmo_filesystemtype_len, 
-			pmo->pmo_data_len);
+			"data = %"PRId32", sock = %"PRId32"\n", 
+			pmo->pmo_source_len, pmo->pmo_target_len, 
+			pmo->pmo_filesystemtype_len, pmo->pmo_data_len,
+			pmo->pmo_sock_len);
 #endif
-	len = pmo->pmo_source_len;
-	source = perfuse_recv_early(fd, len);
+	cp = (char *)(void *)(pmo + 1);
+	
+	if (pmo->pmo_source_len != 0) {
+		source = cp;
+		cp += pmo->pmo_source_len;
+	}
 
-	len = pmo->pmo_target_len;
-	target = perfuse_recv_early(fd, len);
+	if (pmo->pmo_target_len != 0) {
+		target = cp;
+		cp += pmo->pmo_target_len;
+	}
 
-	len = pmo->pmo_filesystemtype_len;
-	filesystemtype = perfuse_recv_early(fd, len);
+	if (pmo->pmo_filesystemtype_len != 0) {
+		filesystemtype = cp;
+		cp += pmo->pmo_filesystemtype_len;
+	}
 
 	mountflags = pmo->pmo_mountflags;
 
-	len = pmo->pmo_data_len;
-	data = perfuse_recv_early(fd, len);
+	if (pmo->pmo_data_len != 0) {
+		data = cp;
+		cp += pmo->pmo_data_len;
+	}
+
+	if (pmo->pmo_sock_len != 0) {
+		sock = cp;
+		cp += pmo->pmo_sock_len;
+	}
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_MISC)
-		DPRINTF("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\")\n", 
+		DPRINTF("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\", \"%s\")\n", 
 		__func__, source, target, filesystemtype, 
-		mountflags, (const char *)data);
+		mountflags, (const char *)data, sock);
 #endif
 	pmi->pmi_source = source;
 	pmi->pmi_target = target;
@@ -176,6 +167,24 @@
 	pmi->pmi_mountflags = (int)mountflags;
 	pmi->pmi_data = data;
 
+	pmi->pmi_uid = cred.sc_euid;
+
+	/*
+	 * Connect to the remote socket, if provided
+	 */
+	if (sock) {
+		const struct sockaddr *sa;
+		struct sockaddr_un sun;
+
+		sa = (const struct sockaddr *)(void *)&sun;
+		sun.sun_len = sizeof(sun);
+		sun.sun_family = AF_LOCAL;
+		strcpy(sun.sun_path, sock);
+
+		if (connect(fd, sa, sun.sun_len) != 0)
+			DERR(EX_OSERR, "connect \"%s\" failed", sun.sun_path);
+	}
+
 	return;
 }
 
@@ -191,7 +200,6 @@
 	pid_t pid;
 	int flags;
 
-
 	pid = (perfuse_diagflags & PDF_FOREGROUND) ? 0 : fork();
 	switch(pid) {
 	case -1:
@@ -211,19 +219,6 @@
 	get_mount_info(fd, &pmi);
 
 	/*
-	 * Get peer identity. If we use socketpair (-i option),
-	 * peer identity if the same as us.
-	 */
-	if (pmnt_flags & PMNT_SOCKPAIR) {
-		pmi.pmi_uid = getuid();
-	} else {
-		if (getpeerid(fd, NULL, &pmi.pmi_uid, NULL) != 0) {
-			DWARNX("Unable to retreive peer identity");
-			pmi.pmi_uid = (uid_t)-1;
-		}
-	}
-
-	/*
 	 * Check that peer owns mountpoint and read (and write) on it?
 	 */
 	ro_flag = pmi.pmi_mountflags & MNT_RDONLY;
@@ -395,23 +390,32 @@
 	s = perfuse_open_sock();
 	
 	do {
+#if (PERFUSE_SOCKTYPE != SOCK_DGRAM)
 		struct sockaddr *sa;
 		struct sockaddr_storage ss;
 		socklen_t ss_len;
+#endif
 		int fd;
 
 #ifdef PERFUSE_DEBUG
 		if (perfuse_diagflags & PDF_MISC)
 			DPRINTF("waiting connexion\n");
 #endif
+#if (PERFUSE_SOCKTYPE == SOCK_DGRAM)
+		fd = s;
+#else
 		sa = (struct sockaddr *)(void *)&ss;
 		ss_len = sizeof(ss);
+
 		if ((fd = accept(s, sa, &ss_len)) == -1)
 			DERR(EX_OSERR,  "accept failed");
+
 #ifdef PERFUSE_DEBUG
 		if (perfuse_diagflags & PDF_MISC)
 			DPRINTF("connexion accepted\n");
-#endif
+#endif /* PERFUSE_DEBUG */
+#endif /* PERFUSE_SOCKTYPE */
+
 		new_mount(fd, PMNT_DEVFUSE);
 	} while (1 /* CONSTCOND */);
 		

Reply via email to