Index: sys/fs/fuse/fuse_device.c =================================================================== --- sys/fs/fuse/fuse_device.c +++ sys/fs/fuse/fuse_device.c @@ -89,6 +89,9 @@ #include "fuse_internal.h" #include "fuse_ipc.h" +#include +#include + SDT_PROVIDER_DECLARE(fusefs); /* * Fuse trace probe: @@ -450,6 +453,15 @@ } if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0) return (err); + + if (data->linux_errnos != 0 && ohead.error != 0) { + err = -ohead.error; + if (err < 0 || err >= sizeof(linux_to_bsd_errtbl)) + return (EINVAL); + + /* '-', because it will get flipped again below */ + ohead.error = -linux_to_bsd_errtbl[err]; + } /* * We check header information (which is redundant) and compare it Index: sys/fs/fuse/fuse_ipc.h =================================================================== --- sys/fs/fuse/fuse_ipc.h +++ sys/fs/fuse/fuse_ipc.h @@ -217,6 +217,7 @@ struct selinfo ks_rsel; int daemon_timeout; + int linux_errnos; unsigned time_gran; uint64_t notimpl; uint64_t mnt_flag; Index: sys/fs/fuse/fuse_vfsops.c =================================================================== --- sys/fs/fuse/fuse_vfsops.c +++ sys/fs/fuse/fuse_vfsops.c @@ -300,6 +300,7 @@ uint64_t mntopts, __mntopts; uint32_t max_read; + int linux_errnos; int daemon_timeout; int fd; @@ -312,6 +313,7 @@ subtype = NULL; max_read = ~0; + linux_errnos = 0; err = 0; mntopts = 0; __mntopts = 0; @@ -337,6 +339,7 @@ FUSE_FLAGOPT(intr, FSESS_INTR); (void)vfs_scanopt(opts, "max_read=", "%u", &max_read); + (void)vfs_scanopt(opts, "linux_errnos", "%d", &linux_errnos); if (vfs_scanopt(opts, "timeout=", "%u", &daemon_timeout) == 1) { if (daemon_timeout < FUSE_MIN_DAEMON_TIMEOUT) daemon_timeout = FUSE_MIN_DAEMON_TIMEOUT; @@ -411,6 +414,7 @@ data->dataflags |= mntopts; data->max_read = max_read; data->daemon_timeout = daemon_timeout; + data->linux_errnos = linux_errnos; data->mnt_flag = mp->mnt_flag & MNT_UPDATEMASK; FUSE_UNLOCK();