From owner-svn-src-head@freebsd.org Mon Nov 9 08:53:16 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 87E722EBFB5; Mon, 9 Nov 2020 08:53:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4CV4XD3FrYz4VXK; Mon, 9 Nov 2020 08:53:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 62A8668C9; Mon, 9 Nov 2020 08:53:16 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0A98rGnC086817; Mon, 9 Nov 2020 08:53:16 GMT (envelope-from trasz@FreeBSD.org) Received: (from trasz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0A98rF4b086813; Mon, 9 Nov 2020 08:53:15 GMT (envelope-from trasz@FreeBSD.org) Message-Id: <202011090853.0A98rF4b086813@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: trasz set sender to trasz@FreeBSD.org using -f From: Edward Tomasz Napierala Date: Mon, 9 Nov 2020 08:53:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r367517 - in head/sys: compat/linux fs/fuse X-SVN-Group: head X-SVN-Commit-Author: trasz X-SVN-Commit-Paths: in head/sys: compat/linux fs/fuse X-SVN-Commit-Revision: 367517 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Nov 2020 08:53:16 -0000 Author: trasz Date: Mon Nov 9 08:53:15 2020 New Revision: 367517 URL: https://svnweb.freebsd.org/changeset/base/367517 Log: Make it possible to mount a fuse filesystem, such as squashfuse, from a Linux binary. Should come handy for AppImages. Reviewed by: asomers MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D26959 Modified: head/sys/compat/linux/linux_file.c head/sys/fs/fuse/fuse_device.c head/sys/fs/fuse/fuse_ipc.h head/sys/fs/fuse/fuse_vfsops.c Modified: head/sys/compat/linux/linux_file.c ============================================================================== --- head/sys/compat/linux/linux_file.c Mon Nov 9 05:20:02 2020 (r367516) +++ head/sys/compat/linux/linux_file.c Mon Nov 9 08:53:15 2020 (r367517) @@ -1181,13 +1181,15 @@ linux_pwritev(struct thread *td, struct linux_pwritev_ int linux_mount(struct thread *td, struct linux_mount_args *args) { - char fstypename[MFSNAMELEN]; - char *mntonname, *mntfromname; + struct mntarg *ma = NULL; + char *fstypename, *mntonname, *mntfromname, *data; int error, fsflags; + fstypename = malloc(MNAMELEN, M_TEMP, M_WAITOK); mntonname = malloc(MNAMELEN, M_TEMP, M_WAITOK); mntfromname = malloc(MNAMELEN, M_TEMP, M_WAITOK); - error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, + data = NULL; + error = copyinstr(args->filesystemtype, fstypename, MNAMELEN - 1, NULL); if (error != 0) goto out; @@ -1208,6 +1210,31 @@ linux_mount(struct thread *td, struct linux_mount_args strcpy(fstypename, "linprocfs"); } else if (strcmp(fstypename, "vfat") == 0) { strcpy(fstypename, "msdosfs"); + } else if (strcmp(fstypename, "fuse") == 0) { + char *fuse_options, *fuse_option, *fuse_name; + + if (strcmp(mntfromname, "fuse") == 0) + strcpy(mntfromname, "/dev/fuse"); + + strcpy(fstypename, "fusefs"); + data = malloc(MNAMELEN, M_TEMP, M_WAITOK); + error = copyinstr(args->data, data, MNAMELEN - 1, NULL); + if (error != 0) + goto out; + + fuse_options = data; + while ((fuse_option = strsep(&fuse_options, ",")) != NULL) { + fuse_name = strsep(&fuse_option, "="); + if (fuse_name == NULL || fuse_option == NULL) + goto out; + ma = mount_arg(ma, fuse_name, fuse_option, -1); + } + + /* + * The FUSE server uses Linux errno values instead of FreeBSD + * ones; add a flag to tell fuse(4) to do errno translation. + */ + ma = mount_arg(ma, "linux_errnos", "1", -1); } fsflags = 0; @@ -1225,14 +1252,15 @@ linux_mount(struct thread *td, struct linux_mount_args if (args->rwflag & LINUX_MS_REMOUNT) fsflags |= MNT_UPDATE; - error = kernel_vmount(fsflags, - "fstype", fstypename, - "fspath", mntonname, - "from", mntfromname, - NULL); + ma = mount_arg(ma, "fstype", fstypename, -1); + ma = mount_arg(ma, "fspath", mntonname, -1); + ma = mount_arg(ma, "from", mntfromname, -1); + error = kernel_mount(ma, fsflags); out: + free(fstypename, M_TEMP); free(mntonname, M_TEMP); free(mntfromname, M_TEMP); + free(data, M_TEMP); return (error); } Modified: head/sys/fs/fuse/fuse_device.c ============================================================================== --- head/sys/fs/fuse/fuse_device.c Mon Nov 9 05:20:02 2020 (r367516) +++ head/sys/fs/fuse/fuse_device.c Mon Nov 9 08:53:15 2020 (r367517) @@ -89,6 +89,9 @@ __FBSDID("$FreeBSD$"); #include "fuse_internal.h" #include "fuse_ipc.h" +#include +#include + SDT_PROVIDER_DECLARE(fusefs); /* * Fuse trace probe: @@ -450,6 +453,15 @@ fuse_device_write(struct cdev *dev, struct uio *uio, i } 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 >= nitems(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 Modified: head/sys/fs/fuse/fuse_ipc.h ============================================================================== --- head/sys/fs/fuse/fuse_ipc.h Mon Nov 9 05:20:02 2020 (r367516) +++ head/sys/fs/fuse/fuse_ipc.h Mon Nov 9 08:53:15 2020 (r367517) @@ -217,6 +217,7 @@ struct fuse_data { struct selinfo ks_rsel; int daemon_timeout; + int linux_errnos; unsigned time_gran; uint64_t notimpl; uint64_t mnt_flag; Modified: head/sys/fs/fuse/fuse_vfsops.c ============================================================================== --- head/sys/fs/fuse/fuse_vfsops.c Mon Nov 9 05:20:02 2020 (r367516) +++ head/sys/fs/fuse/fuse_vfsops.c Mon Nov 9 08:53:15 2020 (r367517) @@ -300,6 +300,7 @@ fuse_vfsop_mount(struct mount *mp) uint64_t mntopts, __mntopts; uint32_t max_read; + int linux_errnos; int daemon_timeout; int fd; @@ -312,6 +313,7 @@ fuse_vfsop_mount(struct mount *mp) subtype = NULL; max_read = ~0; + linux_errnos = 0; err = 0; mntopts = 0; __mntopts = 0; @@ -337,6 +339,7 @@ fuse_vfsop_mount(struct mount *mp) 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 @@ fuse_vfsop_mount(struct mount *mp) 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();