svn commit: r347395 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs

Alan Somers asomers at FreeBSD.org
Thu May 9 16:25:03 UTC 2019


Author: asomers
Date: Thu May  9 16:25:01 2019
New Revision: 347395
URL: https://svnweb.freebsd.org/changeset/base/347395

Log:
  fusefs: create sockets with FUSE_MKNOD, not FUSE_CREATE
  
  libfuse expects sockets to be created with FUSE_MKNOD, not FUSE_CREATE,
  because that's how Linux does it.  My first attempt at creating sockets
  (r346894) used FUSE_CREATE because FreeBSD uses VOP_CREATE for this purpose.
  There are no backwards-compatibility concerns with this change, because
  socket support hasn't yet been merged to head.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_internal.c
  projects/fuse2/sys/fs/fuse/fuse_internal.h
  projects/fuse2/sys/fs/fuse/fuse_vnops.c
  projects/fuse2/tests/sys/fs/fusefs/create.cc
  projects/fuse2/tests/sys/fs/fusefs/fifo.cc
  projects/fuse2/tests/sys/fs/fusefs/mknod.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.c	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.c	Thu May  9 16:25:01 2019	(r347395)
@@ -312,6 +312,19 @@ fuse_internal_fsync(struct vnode *vp,
 	return err;
 }
 
+/* mknod */
+int
+fuse_internal_mknod(struct vnode *dvp, struct vnode **vpp,
+	struct componentname *cnp, struct vattr *vap)
+{
+	struct fuse_mknod_in fmni;
+
+	fmni.mode = MAKEIMODE(vap->va_type, vap->va_mode);
+	fmni.rdev = vap->va_rdev;
+	return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKNOD, &fmni,
+	    sizeof(fmni), vap->va_type));
+}
+
 /* readdir */
 
 int

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.h
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.h	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.h	Thu May  9 16:25:01 2019	(r347395)
@@ -228,6 +228,11 @@ struct pseudo_dirent {
 	uint32_t d_namlen;
 };
 
+/* mknod */
+int fuse_internal_mknod(struct vnode *dvp, struct vnode **vpp,
+	struct componentname *cnp, struct vattr *vap);
+
+/* readdir */
 int fuse_internal_readdir(struct vnode *vp, struct uio *uio,
     struct fuse_filehandle *fufh, struct fuse_iov *cookediov);
 int fuse_internal_readdir_processdata(struct uio *uio, size_t reqsize,

Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c	Thu May  9 16:25:01 2019	(r347395)
@@ -537,6 +537,13 @@ fuse_vnop_create(struct vop_create_args *ap)
 	enum fuse_opcode op;
 	int flags;
 
+	if (fuse_isdeadfs(dvp))
+		return ENXIO;
+
+	/* FUSE expects sockets to be created with FUSE_MKNOD */
+	if (vap->va_type == VSOCK)
+		return fuse_internal_mknod(dvp, vpp, cnp, vap);
+
 	/* 
 	 * VOP_CREATE doesn't tell us the open(2) flags, so we guess.  Only a
 	 * writable mode makes sense, and we might as well include readability
@@ -544,15 +551,12 @@ fuse_vnop_create(struct vop_create_args *ap)
 	 */
 	flags = O_RDWR;
 
-	if (fuse_isdeadfs(dvp)) {
-		return ENXIO;
-	}
 	bzero(&fdi, sizeof(fdi));
 
-	if ((vap->va_type != VREG && vap->va_type != VSOCK))
+	if (vap->va_type != VREG)
 		return (EINVAL);
 
-	if (!fsess_isimpl(mp, FUSE_CREATE)) {
+	if (!fsess_isimpl(mp, FUSE_CREATE) || vap->va_type == VSOCK) {
 		/* Fallback to FUSE_MKNOD/FUSE_OPEN */
 		fdisp_make_mknod_for_fallback(fdip, cnp, dvp, parentnid, td,
 			cred, mode, &op);
@@ -1163,15 +1167,11 @@ fuse_vnop_mknod(struct vop_mknod_args *ap)
 	struct vnode **vpp = ap->a_vpp;
 	struct componentname *cnp = ap->a_cnp;
 	struct vattr *vap = ap->a_vap;
-	struct fuse_mknod_in fmni;
 
 	if (fuse_isdeadfs(dvp))
 		return ENXIO;
 
-	fmni.mode = MAKEIMODE(vap->va_type, vap->va_mode);
-	fmni.rdev = vap->va_rdev;
-	return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKNOD, &fmni,
-	    sizeof(fmni), vap->va_type));
+	return fuse_internal_mknod(dvp, vpp, cnp, vap);
 }
 
 /*

Modified: projects/fuse2/tests/sys/fs/fusefs/create.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/create.cc	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/tests/sys/fs/fusefs/create.cc	Thu May  9 16:25:01 2019	(r347395)
@@ -30,8 +30,6 @@
 
 extern "C" {
 #include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
 }
 
 #include "mockfs.hh"
@@ -308,34 +306,6 @@ TEST_F(Create, ok)
 	fd = open(FULLPATH, O_CREAT | O_EXCL, mode);
 	EXPECT_LE(0, fd) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
-}
-
-/* Create a unix-domain socket */
-TEST_F(Create, socket)
-{
-	const char FULLPATH[] = "mountpoint/some_sock";
-	const char RELPATH[] = "some_sock";
-	mode_t mode = S_IFSOCK | 0755;
-	struct sockaddr_un sa;
-	uint64_t ino = 42;
-	int fd;
-
-	EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT)));
-	expect_create(RELPATH, mode,
-		ReturnImmediate([=](auto in __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, create);
-		out->body.create.entry.attr.mode = mode;
-		out->body.create.entry.nodeid = ino;
-		out->body.create.entry.entry_valid = UINT64_MAX;
-		out->body.create.entry.attr_valid = UINT64_MAX;
-	}));
-
-	fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	ASSERT_LE(0, fd) << strerror(errno);
-	sa.sun_family = AF_UNIX;
-	strlcpy(sa.sun_path, FULLPATH, sizeof(sa.sun_path));
-	ASSERT_EQ(0, bind(fd, (struct sockaddr*)&sa, sizeof(sa)))
-		<< strerror(errno);
 }
 
 /*

Modified: projects/fuse2/tests/sys/fs/fusefs/fifo.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/fifo.cc	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/tests/sys/fs/fusefs/fifo.cc	Thu May  9 16:25:01 2019	(r347395)
@@ -159,17 +159,18 @@ TEST_F(Socket, read_write)
 	EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT)));
 	EXPECT_CALL(*m_mock, process(
 		ResultOf([=](auto in) {
-			return (in->header.opcode == FUSE_CREATE);
+			return (in->header.opcode == FUSE_MKNOD);
 		}, Eq(true)),
 		_)
 	).InSequence(seq)
 	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {
-		SET_OUT_HEADER_LEN(out, create);
-		out->body.create.entry.attr.mode = mode;
-		out->body.create.entry.nodeid = ino;
-		out->body.create.entry.entry_valid = UINT64_MAX;
-		out->body.create.entry.attr_valid = UINT64_MAX;
+		SET_OUT_HEADER_LEN(out, entry);
+		out->body.entry.attr.mode = mode;
+		out->body.entry.nodeid = ino;
+		out->body.entry.entry_valid = UINT64_MAX;
+		out->body.entry.attr_valid = UINT64_MAX;
 	})));
+
 	EXPECT_LOOKUP(1, RELPATH)
 	.InSequence(seq)
 	.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto out) {

Modified: projects/fuse2/tests/sys/fs/fusefs/mknod.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/mknod.cc	Thu May  9 14:06:24 2019	(r347394)
+++ projects/fuse2/tests/sys/fs/fusefs/mknod.cc	Thu May  9 16:25:01 2019	(r347395)
@@ -30,6 +30,8 @@
 
 extern "C" {
 #include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 }
 
 #include "mockfs.hh"
@@ -135,6 +137,28 @@ TEST_F(Mknod, fifo)
 	dev_t rdev = VNOVAL;		/* Fifos don't have device numbers */
 	expect_mknod(mode, rdev);
 	EXPECT_EQ(0, mkfifo(FULLPATH, mode)) << strerror(errno);
+}
+
+/*
+ * Create a unix-domain socket.
+ *
+ * This test case doesn't actually need root privileges.
+ */
+TEST_F(Mknod, socket)
+{
+	mode_t mode = S_IFSOCK | 0755;
+	struct sockaddr_un sa;
+	int fd;
+	dev_t rdev = -1;	/* Really it's a don't care */
+
+	expect_mknod(mode, rdev);
+
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	ASSERT_LE(0, fd) << strerror(errno);
+	sa.sun_family = AF_UNIX;
+	strlcpy(sa.sun_path, FULLPATH, sizeof(sa.sun_path));
+	ASSERT_EQ(0, bind(fd, (struct sockaddr*)&sa, sizeof(sa)))
+		<< strerror(errno);
 }
 
 /* 


More information about the svn-src-projects mailing list