Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Jun 2025 06:11:41 GMT
From:      Gleb Popov <arrowd@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f9c9122d5ab9 - main - fusefs: First take on exterrorizing
Message-ID:  <202506170611.55H6Bfgt044652@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by arrowd:

URL: https://cgit.FreeBSD.org/src/commit/?id=f9c9122d5ab9b106ddc6897454350b31de838631

commit f9c9122d5ab9b106ddc6897454350b31de838631
Author:     Gleb Popov <arrowd@FreeBSD.org>
AuthorDate: 2025-06-13 10:38:35 +0000
Commit:     Gleb Popov <arrowd@FreeBSD.org>
CommitDate: 2025-06-17 06:11:34 +0000

    fusefs: First take on exterrorizing
    
    Reviewed by:    kib, asomers
    Approved by:    kib, asomers
    Differential Revision: https://reviews.freebsd.org/D50831
---
 sys/fs/fuse/fuse_device.c | 34 +++++++++++++++++++++-------------
 sys/fs/fuse/fuse_vfsops.c | 33 +++++++++++++++++++++------------
 sys/sys/exterr_cat.h      |  1 +
 3 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index 0a5da63c1f54..b0c886d4b120 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -82,6 +82,8 @@
 #include <sys/sysctl.h>
 #include <sys/poll.h>
 #include <sys/selinfo.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FUSE
+#include <sys/exterrvar.h>
 
 #include "fuse.h"
 #include "fuse_internal.h"
@@ -193,7 +195,7 @@ fuse_device_filter(struct cdev *dev, struct knote *kn)
 		kn->kn_fop = &fuse_device_wfiltops;
 		error = 0;
 	} else if (error == 0) {
-		error = EINVAL;
+		error = EXTERROR(EINVAL, "Unsupported kevent filter");
 		kn->kn_data = error;
 	}
 
@@ -319,7 +321,7 @@ again:
 			"we know early on that reader should be kicked so we "
 			"don't wait for news");
 		fuse_lck_mtx_unlock(data->ms_mtx);
-		return (ENODEV);
+		return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
 	}
 	if (!(tick = fuse_ms_pop(data))) {
 		/* check if we may block */
@@ -331,7 +333,10 @@ again:
 			err = msleep(data, &data->ms_mtx, PCATCH, "fu_msg", 0);
 			if (err != 0) {
 				fuse_lck_mtx_unlock(data->ms_mtx);
-				return (fdata_get_dead(data) ? ENODEV : err);
+				if (fdata_get_dead(data))
+					err = EXTERROR(ENODEV,
+						"This FUSE session is about to be closed");
+				return (err);
 			}
 			tick = fuse_ms_pop(data);
 		}
@@ -361,8 +366,8 @@ again:
 			FUSE_ASSERT_MS_DONE(tick);
 			fuse_ticket_drop(tick);
 		}
-		return (ENODEV);	/* This should make the daemon get off
-					 * of us */
+		/* This should make the daemon get off of us */
+		return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
 	}
 	SDT_PROBE2(fusefs, , device, trace, 1,
 		"fuse device read message successfully");
@@ -385,7 +390,7 @@ again:
 		fdata_set_dead(data);
 		SDT_PROBE2(fusefs, , device, trace, 2,
 		    "daemon is stupid, kick it off...");
-		err = ENODEV;
+		err = EXTERROR(ENODEV, "Partial read attempted");
 	} else {
 		err = uiomove(buf, buflen, uio);
 	}
@@ -403,12 +408,14 @@ fuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio)
 		SDT_PROBE2(fusefs, , device, trace, 1,
 			"Format error: body size "
 			"differs from size claimed by header");
-		return (EINVAL);
+		return (EXTERROR(EINVAL, "Format error: body size "
+		    "differs from size claimed by header"));
 	}
 	if (uio->uio_resid && ohead->unique != 0 && ohead->error) {
 		SDT_PROBE2(fusefs, , device, trace, 1, 
 			"Format error: non zero error but message had a body");
-		return (EINVAL);
+		return (EXTERROR(EINVAL, "Format error: non zero error, "
+		    "but message had a body"));
 	}
 
 	return (0);
@@ -444,7 +451,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
 		SDT_PROBE2(fusefs, , device, trace, 1,
 			"fuse_device_write got less than a header!");
 		fdata_set_dead(data);
-		return (EINVAL);
+		return (EXTERROR(EINVAL, "fuse_device_write got less than a header!"));
 	}
 	if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0)
 		return (err);
@@ -452,7 +459,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
 	if (data->linux_errnos != 0 && ohead.error != 0) {
 		err = -ohead.error;
 		if (err < 0 || err >= nitems(linux_to_bsd_errtbl))
-			return (EINVAL);
+			return (EXTERROR(EINVAL, "Unknown Linux errno", err));
 
 		/* '-', because it will get flipped again below */
 		ohead.error = -linux_to_bsd_errtbl[err];
@@ -520,7 +527,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
 				memcpy(&tick->tk_aw_ohead, &ohead,
 					sizeof(ohead));
 				tick->tk_aw_handler(tick, uio);
-				err = EINVAL;
+				err = EXTERROR(EINVAL, "Unknown errno", ohead.error);
 			} else {
 				memcpy(&tick->tk_aw_ohead, &ohead,
 					sizeof(ohead));
@@ -570,7 +577,8 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
 			/* Unimplemented.  See comments in fuse_vnops */
 		default:
 			/* Not implemented */
-			err = ENOSYS;
+			err = EXTERROR(ENOSYS, "Unimplemented FUSE notification code",
+				ohead.error);
 		}
 		vfs_unbusy(mp);
 	} else {
@@ -589,7 +597,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
 			 */
 			err = 0;
 		} else {
-			err = EINVAL;
+			err = EXTERROR(ENOSYS, "FUSE ticket is missing");
 		}
 	}
 
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index 48b84d3c75af..1b858a988289 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -81,6 +81,8 @@
 #include <sys/mount.h>
 #include <sys/sysctl.h>
 #include <sys/fcntl.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FUSE
+#include <sys/exterrvar.h>
 
 #include "fuse.h"
 #include "fuse_node.h"
@@ -272,7 +274,7 @@ fuse_vfsop_fhtovp(struct mount *mp, struct fid *fhp, int flags,
 	int error;
 
 	if (!(fuse_get_mpdata(mp)->dataflags & FSESS_EXPORT_SUPPORT))
-		return EOPNOTSUPP;
+		return (EXTERROR(EOPNOTSUPP, "NFS-style lookups are not supported"));
 
 	error = VFS_VGET(mp, ffhp->nid, LK_EXCLUSIVE, &nvp);
 	if (error) {
@@ -321,11 +323,11 @@ fuse_vfsop_mount(struct mount *mp)
 	opts = mp->mnt_optnew;
 
 	if (!opts)
-		return EINVAL;
+		return (EXTERROR(EINVAL, "Mount options were not supplied"));
 
 	/* `fspath' contains the mount point (eg. /mnt/fuse/sshfs); REQUIRED */
 	if (!vfs_getopts(opts, "fspath", &err))
-		return err;
+		return (EXTERROR(err, "Mount options are missing 'fspath'"));
 
 	/*
 	 * With the help of underscored options the mount program
@@ -358,11 +360,12 @@ fuse_vfsop_mount(struct mount *mp)
 	/* `from' contains the device name (eg. /dev/fuse0); REQUIRED */
 	fspec = vfs_getopts(opts, "from", &err);
 	if (!fspec)
-		return err;
+		return (EXTERROR(err, "Mount options are missing 'from'"));
 
 	/* `fd' contains the filedescriptor for this session; REQUIRED */
 	if (vfs_scanopt(opts, "fd", "%d", &fd) != 1)
-		return EINVAL;
+		return (EXTERROR(EINVAL, "Mount options contain an invalid value "
+		    "for 'fd'"));
 
 	err = fuse_getdevice(fspec, td, &fdev);
 	if (err != 0)
@@ -398,11 +401,17 @@ fuse_vfsop_mount(struct mount *mp)
 	/* Sanity + permission checks */
 	if (!data->daemoncred)
 		panic("fuse daemon found, but identity unknown");
-	if (mntopts & FSESS_DAEMON_CAN_SPY)
+	if (mntopts & FSESS_DAEMON_CAN_SPY) {
 		err = priv_check(td, PRIV_VFS_FUSE_ALLOWOTHER);
-	if (err == 0 && td->td_ucred->cr_uid != data->daemoncred->cr_uid)
+		EXTERROR(err, "FUSE daemon requires privileges "
+		    "due to 'allow_other' option");
+	}
+	if (err == 0 && td->td_ucred->cr_uid != data->daemoncred->cr_uid) {
 		/* are we allowed to do the first mount? */
 		err = priv_check(td, PRIV_VFS_FUSE_MOUNT_NONUSER);
+		EXTERROR(err, "Mounting as a user that is different from the FUSE "
+		    "daemon's requires privileges");
+	}
 	if (err) {
 		FUSE_UNLOCK();
 		goto out;
@@ -549,7 +558,7 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 		 * nullfs mount of a fusefs file system.
 		 */
 		SDT_PROBE1(fusefs, , vfsops, invalidate_without_export, mp);
-		return (EOPNOTSUPP);
+		return (EXTERROR(EOPNOTSUPP, "NFS-style lookups are not supported"));
 	}
 
 	error = fuse_internal_get_cached_vnode(mp, ino, flags, vpp);
@@ -580,10 +589,10 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 		 * Something is very wrong with the server if "foo/." has a
 		 * different inode number than "foo".
 		 */
-		fuse_warn(data, FSESS_WARN_DOT_LOOKUP,
-		    "Inconsistent LOOKUP response: \"FILE/.\" has a different "
-		    "inode number than \"FILE\".");
-		error = EIO;
+		static const char exterr[] = "Inconsistent LOOKUP response: "
+		    "\"FILE/.\" has a different inode number than \"FILE\".";
+		fuse_warn(data, FSESS_WARN_DOT_LOOKUP, exterr);
+		error = EXTERROR(EIO, exterr);
 		goto out;
 	}
 
diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h
index adb474e84c1b..d770c274d7b7 100644
--- a/sys/sys/exterr_cat.h
+++ b/sys/sys/exterr_cat.h
@@ -15,6 +15,7 @@
 #define	EXTERR_CAT_FILEDESC	2
 #define	EXTERR_KTRACE		3	/* To allow inclusion of this
 					   file into kern_ktrace.c */
+#define	EXTERR_CAT_FUSE		4
 
 #endif
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506170611.55H6Bfgt044652>