Module Name:    src
Committed By:   manu
Date:           Mon May 30 14:50:08 UTC 2011

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

Log Message:
Use SOCK_SEQPACKET in perfuse if available. This fix file operations hangs
where the FUSE filesyste replied to an operation and got an ENOBUFS it did
not handle.

We now are also able to cleanly unmount


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.14 -r1.15 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.12 -r1.13 src/lib/libperfuse/perfuse_if.h
cvs rdiff -u -r1.17 -r1.18 src/lib/libperfuse/perfuse_priv.h
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/perfused/msg.c \
    src/usr.sbin/perfused/perfused.c
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/perfused/perfused.h

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/ops.c
diff -u src/lib/libperfuse/ops.c:1.27 src/lib/libperfuse/ops.c:1.28
--- src/lib/libperfuse/ops.c:1.27	Wed May 18 15:28:12 2011
+++ src/lib/libperfuse/ops.c	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.27 2011/05/18 15:28:12 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.28 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -844,9 +844,12 @@
 			goto out;
 	}
 
-	DPRINTF("%s unmounted, exit\n", ps->ps_target);
+	ps->ps_umount(pu);
 
-	exit(0);
+	if (perfuse_diagflags & PDF_MISC)
+		DPRINTF("%s unmounted, exit\n", ps->ps_target);
+
+	return 0;
 out:
 	ps->ps_destroy_msg(pm);
 	

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.14 src/lib/libperfuse/perfuse.c:1.15
--- src/lib/libperfuse/perfuse.c:1.14	Wed May 18 15:25:19 2011
+++ src/lib/libperfuse/perfuse.c	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.14 2011/05/18 15:25:19 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.15 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -148,15 +148,25 @@
 	char *const argv[] = { progname, minus_i, fdstr, NULL};
 	uint32_t opt;
 	uint32_t optlen;
+	int sock_type = SOCK_SEQPACKET;
 
 	if (strcmp(path, _PATH_FUSE) != 0)
 		return open(path, flags, mode);
 
-	if ((sv[0] = socket(PF_LOCAL, SOCK_DGRAM, 0)) == -1) {
+	/* 
+	 * Try SOCK_SEQPACKET then SOCK_DGRAM if unavailable
+	 */
+	if ((sv[0] = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) == -1) {
+		sock_type = SOCK_DGRAM;
+                DWARNX("SEQPACKET local sockets unavailable, using less "
+		       "reliable DGRAM sockets. Expect file operation hangs.");
+
+		if ((sv[0] = socket(PF_LOCAL, SOCK_DGRAM, 0)) == -1) {
 #ifdef PERFUSE_DEBUG
-		DWARN("%s:%d socket failed: %s", __func__, __LINE__);
+			DWARN("%s:%d socket failed: %s", __func__, __LINE__);
 #endif
-		return -1;
+			return -1;
+		}
 	}
 
 	/*
@@ -178,17 +188,16 @@
 	sun.sun_family = AF_LOCAL;
 	(void)strcpy(sun.sun_path, path);
 
-	if (connect(sv[0], sa, (socklen_t)sun.sun_len) == 0) 
+	if (connect(sv[0], sa, (socklen_t)sun.sun_len) == 0)
 		return sv[0];
 
-
 	/*
 	 * Attempt to run perfused on our own
 	 * if it does not run yet; In that case
 	 * we will talk using a socketpair 
 	 * instead of /dev/fuse.
 	 */
-	if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, sv) != 0) {
+	if (socketpair(PF_LOCAL, sock_type, 0, sv) != 0) {
 		DWARN("%s:%d: socketpair failed", __func__, __LINE__);
 		return -1;
 	}
@@ -510,6 +519,7 @@
 	ps->ps_get_inpayload = pc->pc_get_inpayload;
 	ps->ps_get_outhdr = pc->pc_get_outhdr;
 	ps->ps_get_outpayload = pc->pc_get_outpayload;
+	ps->ps_umount = pc->pc_umount;
 
 	return pu;
 } 
@@ -558,12 +568,15 @@
 	ps = puffs_getspecific(pu);
 
 	ps->ps_flags |= PS_INLOOP;
-	if (puffs_mainloop(ps->ps_pu) != 0)
+	if (puffs_mainloop(ps->ps_pu) != 0) {
 		DERR(EX_OSERR, "puffs_mainloop failed");
-	DERR(EX_OSERR, "puffs_mainloop exit");
+		return -1;
+	}
 
-	/* NOTREACHED */
-	return -1;
+	/* 
+	 * Normal exit after unmount
+	 */
+	return 0;
 }
 
 /* ARGSUSED0 */

Index: src/lib/libperfuse/perfuse_if.h
diff -u src/lib/libperfuse/perfuse_if.h:1.12 src/lib/libperfuse/perfuse_if.h:1.13
--- src/lib/libperfuse/perfuse_if.h:1.12	Wed May 18 15:22:54 2011
+++ src/lib/libperfuse/perfuse_if.h	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_if.h,v 1.12 2011/05/18 15:22:54 manu Exp $ */
+/*  $NetBSD: perfuse_if.h,v 1.13 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -134,6 +134,7 @@
 typedef struct fuse_in_header *(*perfuse_get_inhdr_fn)(perfuse_msg_t *);
 typedef char *(*perfuse_get_inpayload_fn)(perfuse_msg_t *);
 typedef char *(*perfuse_get_outpayload_fn)(perfuse_msg_t *);
+typedef void (*perfuse_umount_fn)(struct puffs_usermount *);
 
 struct perfuse_callbacks {
 	perfuse_new_msg_fn pc_new_msg;
@@ -143,6 +144,7 @@
 	perfuse_get_inpayload_fn pc_get_inpayload;
 	perfuse_get_outhdr_fn pc_get_outhdr;
 	perfuse_get_outpayload_fn pc_get_outpayload;
+	perfuse_umount_fn pc_umount;
 };
 
 /* 

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.17 src/lib/libperfuse/perfuse_priv.h:1.18
--- src/lib/libperfuse/perfuse_priv.h:1.17	Mon Apr 25 04:54:53 2011
+++ src/lib/libperfuse/perfuse_priv.h	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.17 2011/04/25 04:54:53 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.18 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -65,6 +65,7 @@
 	perfuse_get_inpayload_fn ps_get_inpayload;
 	perfuse_get_outhdr_fn ps_get_outhdr;
 	perfuse_get_outpayload_fn ps_get_outpayload;
+	perfuse_umount_fn ps_umount;
 };
 
 

Index: src/usr.sbin/perfused/msg.c
diff -u src/usr.sbin/perfused/msg.c:1.12 src/usr.sbin/perfused/msg.c:1.13
--- src/usr.sbin/perfused/msg.c:1.12	Mon May  9 08:51:18 2011
+++ src/usr.sbin/perfused/msg.c	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: msg.c,v 1.12 2011/05/09 08:51:18 manu Exp $ */
+/*  $NetBSD: msg.c,v 1.13 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -56,11 +56,22 @@
 	struct sockaddr_un sun;
 	const struct sockaddr *sa;
 	uint32_t opt;
+	int sock_type = SOCK_SEQPACKET;
 
 	(void)unlink(_PATH_FUSE);
 
-	if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1)
-		err(EX_OSERR, "socket failed");
+	/*
+	 * Try SOCK_SEQPACKET and fallback to SOCK_DGRAM 
+	 * if unavaible
+	 */
+	if ((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) == -1) {
+		warnx("SEQPACKET local sockets unavailable, using less "
+		      "reliable DGRAM sockets. Expect file operation hangs.");
+
+		sock_type = SOCK_DGRAM;
+		if ((s = socket(PF_LOCAL, SOCK_DGRAM, 0)) == -1)
+			err(EX_OSERR, "socket failed");
+	}
 
 	sa = (const struct sockaddr *)(void *)&sun;
 	sun.sun_len = sizeof(sun);
@@ -90,8 +101,10 @@
 	if (bind(s, sa, (socklen_t )sun.sun_len) == -1)
 		err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
 
-	if (connect(s, sa, (socklen_t )sun.sun_len) == -1)
-		err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
+	if (sock_type == SOCK_DGRAM) {
+		if (connect(s, sa, (socklen_t )sun.sun_len) == -1)
+			err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
+	}
 
 	return s;
 }
@@ -580,6 +593,7 @@
 		switch(errno) {
 		case EAGAIN:
 		case ENOBUFS:
+		case EMSGSIZE:
 			return 0;
 			break;
 		default:
@@ -676,3 +690,20 @@
 	/* NOTREACHED */
 	return;
 }
+
+void
+perfuse_umount(pu)
+	struct puffs_usermount *pu;
+{
+	int fd;
+
+	fd = (int)(long)perfuse_getspecific(pu);
+
+	if (shutdown(fd, SHUT_RDWR) != 0)
+		DWARN("shutdown() failed");
+
+	if (perfuse_diagflags & PDF_MISC)
+		DPRINTF("unmount");
+
+	return;
+}
Index: src/usr.sbin/perfused/perfused.c
diff -u src/usr.sbin/perfused/perfused.c:1.12 src/usr.sbin/perfused/perfused.c:1.13
--- src/usr.sbin/perfused/perfused.c:1.12	Mon Apr 25 04:30:59 2011
+++ src/usr.sbin/perfused/perfused.c	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfused.c,v 1.12 2011/04/25 04:30:59 manu Exp $ */
+/*  $NetBSD: perfused.c,v 1.13 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -55,7 +55,7 @@
 static int parse_debug(char *);
 static void siginfo_handler(int);
 static int parse_options(int, char **);
-static void get_mount_info(int, struct perfuse_mount_info *);
+static void get_mount_info(int, struct perfuse_mount_info *, int);
 int main(int, char **);
 
 /*
@@ -63,6 +63,7 @@
  */
 #define  PMNT_DEVFUSE	0x0	/* We use /dev/fuse */
 #define  PMNT_SOCKPAIR	0x1	/* We use socketpair */
+#define  PMNT_DGRAM	0x2	/* We use SOCK_DGRAM sockets */
 
 
 static int
@@ -94,9 +95,10 @@
 }
 
 static void
-get_mount_info(fd, pmi)
+get_mount_info(fd, pmi, sock_type)
 	int fd;
 	struct perfuse_mount_info *pmi;
+	int sock_type;
 {
 	struct perfuse_mount_out *pmo;
 	struct sockcred cred;
@@ -178,9 +180,9 @@
 	pmi->pmi_uid = cred.sc_euid;
 
 	/*
-	 * Connect to the remote socket, if provided
+	 * Connect to the remote socket if provided ans using SOCK_DGRAM
 	 */
-	if (sock) {
+	if ((sock_type == SOCK_DGRAM) && sock) {
 		const struct sockaddr *sa;
 		struct sockaddr_un sun;
 
@@ -207,6 +209,7 @@
 	int ro_flag;
 	pid_t pid;
 	int flags;
+	int sock_type;
 
 	pid = (perfuse_diagflags & PDF_FOREGROUND) ? 0 : fork();
 	switch(pid) {
@@ -224,7 +227,8 @@
 	/*
 	 * Mount information (source, target, mount flags...)
 	 */
-	get_mount_info(fd, &pmi);
+	sock_type = pmnt_flags & PMNT_DGRAM ? SOCK_DGRAM : SOCK_SEQPACKET;
+	get_mount_info(fd, &pmi, sock_type);
 
 	/*
 	 * Check that peer owns mountpoint and read (and write) on it?
@@ -245,6 +249,7 @@
 	pc.pc_get_inpayload = perfuse_get_inpayload;
 	pc.pc_get_outhdr = perfuse_get_outhdr;
 	pc.pc_get_outpayload = perfuse_get_outpayload;
+	pc.pc_umount = perfuse_umount;
 
 	pu = perfuse_init(&pc, &pmi);
 	
@@ -273,11 +278,12 @@
 	/*
 	 * Hand over control to puffs main loop.
 	 */
-	(void)perfuse_mainloop(pu);
+	if (perfuse_mainloop(pu) != 0)
+		DERRX(EX_SOFTWARE, "perfuse_mainloop exit");
 
-	DERRX(EX_SOFTWARE, "perfuse_mainloop exit");
-
-	/* NOTREACHED */
+	/*	
+	 * Normal return after unmount
+	 */
 	return;
 }
 
@@ -313,7 +319,7 @@
 		else if (strcmp(opt, "filename") == 0)
 			retval |= PDF_FILENAME;
 		else
-			DERRX(EX_USAGE, "unknown debug flag \"%s\"", opt);
+			DWARNX("unknown debug flag \"%s\"", opt);
 	}
 
 	return retval;
@@ -382,6 +388,8 @@
 	char **argv;
 {
 	int s;
+	int sock_type;
+	socklen_t len;
 
 	s = parse_options(argc, argv);
 
@@ -394,18 +402,45 @@
 
 	if (s != -1) {
 		new_mount(s, PMNT_SOCKPAIR);
-		DERRX(EX_SOFTWARE, "new_mount exit while -i is used");
+		exit(0);
 	}
 
 	s = perfuse_open_sock();
 	
-	do {
 #ifdef PERFUSE_DEBUG
-		if (perfuse_diagflags & PDF_MISC)
-			DPRINTF("perfused ready\n");
+	if (perfuse_diagflags & PDF_MISC)
+		DPRINTF("perfused ready\n");
 #endif
-		new_mount(s, PMNT_DEVFUSE);
-	} while (1 /* CONSTCOND */);
+	len = sizeof(sock_type);
+	if (getsockopt(s, SOL_SOCKET, SO_TYPE, &sock_type, &len) != 0)
+		DERR(EX_OSERR, "getsockopt SO_TYPE failed");
+
+	switch(sock_type) {
+	case SOCK_DGRAM:
+		new_mount(s, PMNT_DEVFUSE|PMNT_DGRAM);
+		exit(0);
+		break;
+	case SOCK_SEQPACKET:
+		if (listen(s, 0) != 0)
+			DERR(EX_OSERR, "listen failed");
+
+		do {
+			int fd;
+			struct sockaddr_un sun;
+			struct sockaddr *sa;
+		
+			len = sizeof(sun);
+			sa = (struct sockaddr *)(void *)&sun;
+			if ((fd = accept(s, sa, &len)) == -1)
+				DERR(EX_OSERR, "accept failed");
+
+			new_mount(fd, PMNT_DEVFUSE);
+		} while (1 /* CONSTCOND */);
+		break;
+	default:
+		DERRX(EX_SOFTWARE, "unexpected so_type %d", sock_type);
+		break;
+	}
 		
 	/* NOTREACHED */
 	return 0;

Index: src/usr.sbin/perfused/perfused.h
diff -u src/usr.sbin/perfused/perfused.h:1.3 src/usr.sbin/perfused/perfused.h:1.4
--- src/usr.sbin/perfused/perfused.h:1.3	Wed Sep 15 01:51:44 2010
+++ src/usr.sbin/perfused/perfused.h	Mon May 30 14:50:08 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfused.h,v 1.3 2010/09/15 01:51:44 manu Exp $ */
+/*  $NetBSD: perfused.h,v 1.4 2011/05/30 14:50:08 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -57,6 +57,7 @@
 struct fuse_in_header *perfuse_get_inhdr(perfuse_msg_t *);
 char *perfuse_get_inpayload(perfuse_msg_t *);
 char *perfuse_get_outpayload(perfuse_msg_t *);
+void perfuse_umount(struct puffs_usermount *);
 
 perfuse_msg_t *perfuse_new_pb(struct puffs_usermount *, 
     puffs_cookie_t, int, size_t, const struct puffs_cred *);

Reply via email to