{"id":2226967,"url":"http://patchwork.ozlabs.org/api/patches/2226967/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ext4/patch/177689989662.3821326.17747399801399376401.stgit@frogsfrogsfrogs/","project":{"id":8,"url":"http://patchwork.ozlabs.org/api/projects/8/?format=json","name":"Linux ext4 filesystem development","link_name":"linux-ext4","list_id":"linux-ext4.vger.kernel.org","list_email":"linux-ext4@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<177689989662.3821326.17747399801399376401.stgit@frogsfrogsfrogs>","list_archive_url":null,"date":"2026-04-22T23:25:24","name":"[07/10] fuse4fs: enable safe service mode","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"97cc81a6a41d3a576edbf9c837ddd9da0d46af83","submitter":{"id":77032,"url":"http://patchwork.ozlabs.org/api/people/77032/?format=json","name":"Darrick J. Wong","email":"djwong@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-ext4/patch/177689989662.3821326.17747399801399376401.stgit@frogsfrogsfrogs/mbox/","series":[{"id":501127,"url":"http://patchwork.ozlabs.org/api/series/501127/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ext4/list/?series=501127","date":"2026-04-22T23:23:47","name":"[01/10] libext2fs: make it possible to extract the fd from an IO manager","version":1,"mbox":"http://patchwork.ozlabs.org/series/501127/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2226967/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2226967/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <SRS0=lfQK=CV=vger.kernel.org=linux-ext4+bounces-16011-patchwork-incoming=ozlabs.org@ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-ext4@vger.kernel.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","patchwork-incoming@ozlabs.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=jOTJF9F/;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=150.107.74.76; helo=mail.ozlabs.org;\n envelope-from=srs0=lfqk=cv=vger.kernel.org=linux-ext4+bounces-16011-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)","gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=\"2600:3c0a:e001:db::12fc:5321\"\n arc.chain=subspace.kernel.org","gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org","gandalf.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=jOTJF9F/;\n\tdkim-atps=neutral","gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16011-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"jOTJF9F/\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1FlB0bpgz1yDD\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 09:28:06 +1000 (AEST)","from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4g1FlB08hbz4wCM\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 09:28:06 +1000 (AEST)","by gandalf.ozlabs.org (Postfix)\n\tid 4g1FlB04zYz4wHx; Thu, 23 Apr 2026 09:28:06 +1000 (AEST)","from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4g1Fl643bdz4wCM\n\tfor <patchwork-incoming@ozlabs.org>; Thu, 23 Apr 2026 09:28:02 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 5050730E7D7D\n\tfor <patchwork-incoming@ozlabs.org>; Wed, 22 Apr 2026 23:25:27 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id CDA823A3833;\n\tWed, 22 Apr 2026 23:25:25 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F9E61D6DA9;\n\tWed, 22 Apr 2026 23:25:25 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 60110C2BCAF;\n\tWed, 22 Apr 2026 23:25:25 +0000 (UTC)"],"ARC-Seal":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1776900485; cv=pass;\n\tb=wrSfQ3QkEPx5eTI//Ulht/hk1U1Q0OJmumX8UQZOFzWK5oPjpl6toum3+Cv+GbCgg+Euq5dyWN8PZnnA+kNlT4mzDAv8brciAopzvMffEFVii3gpQBSR7ySerjEXJu5eeE0HBJdmF1xKWuYGEBr/oX4eWXn/qfrq7TOMJyvzP3GY6sk4tE3mIb4pDrHXuDH1xJ64oFxDHXvseAsZJXz/GGa8vgGLs1SzWQBwriio2N3/+5aPyZWFm5xthkHzUXTu7NVK+CNn0+hOz0acT/ah+OMf49lloZbzerWMIJfL4R4XoekkzjcQDc0x9Fav8ugGR0en+W2/9g7vMMwnk3+YLg==","i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776900325; cv=none;\n b=O+4lcHrpgMjToypIRfCKWfimt1EsaNPz0KsqSkA7lKtXqGmqJlbDwvT2Y2mwTNC7LbPo7UIPX51BPHvyhraNFjGqVUWAdXq6WLoWxkDYMkk5+1q8SAOi+bt6TEGTfqiLHlp3akwdc0VRWzFuBVcGFJE4YjxePV1310Lh7raHkz0="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1776900485; c=relaxed/relaxed;\n\tbh=r0LaNDvPrD5vCgraFbkwXDyY3u64W/EEG7Sh4ulbv9I=;\n\th=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Type;\n b=j/bCtjbNk4e4sodDbLItmBI8DH9Q5i2l9CC/ZTQzF3FtTsm+PxT5u1qUotr7BH0WSDCl3zc2nChONe1iMhk3X9P3muzQTQMn6gszsuFAP3giZhjVFL/9LRzHCt6I5g2G+EOGA7GZ/ZlPRmmtjJg6E6lUMxxtIJ+utKSmKM9qyCfH7Tkd+gj+/nQak2dvU4gkKKUPG/EtlXwg9AFvvKGl0hqj+uEwLY0WvgZAAHkLLm6EKo56op0RNt40X6U3qSDsKHpOWxEo3fgl+mXHM4bYzmEBwbbHgARdHWEUiNUIZcV20jb+ngRT8Kgl8uWPQY6N0m7N9DCOAGOSKO9/po30Gw==","i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776900325; c=relaxed/simple;\n\tbh=mVTZ711hi/oV1AHU5TAJx2m3cALFU3F78q4eKDyVPiA=;\n\th=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Type;\n b=phcDLRfoxMxzWKsQQg7ZdfR+w5CsLCBjrZv8jIs582e98qhvEuvaSlP6M1oNf6w8XGnPNU8ZPLysXPQbzI7SA51mZjDK2gypTqyJL2xTq+m/U7lJCgXsER2+vSaf028NpUglX953AlRqVIXhgvgrWBllm+0knUwgfEHy33t8gR0="],"ARC-Authentication-Results":["i=2; gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org;\n dkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=jOTJF9F/; dkim-atps=neutral;\n spf=pass (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16011-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org","i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=jOTJF9F/; arc=none smtp.client-ip=10.30.226.201"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1776900325;\n\tbh=mVTZ711hi/oV1AHU5TAJx2m3cALFU3F78q4eKDyVPiA=;\n\th=Date:Subject:From:To:Cc:In-Reply-To:References:From;\n\tb=jOTJF9F/UradWRLGrz7F3+6VCJIqtlSmFdRXTPiWp+ik1D3zoLCM3noQHi7x7V70o\n\t ODKJJk/m94vbSX/vPGeerigEzZuM52r1frYqtICU1nBTKGc8P1Z25irL7NfivLc9cG\n\t LzW+jz6G6vB5twni8k4z7ZoV/ejZwypRjvdOj1J8u3kWgUq0LP2Ay1zzrASCV51Knb\n\t IzE3Qhq1w1QBPS6a6d3CXFxwxH4w/lkXysiGN0suELObN2Qd2+uKpEKBYjbrhjd5f2\n\t 1tE2UF9oQUqieFJbZsXuoniD2zPsoLzUVsgIin3F2+7C1FAYDMQ1DDwsKm1tGTgDO8\n\t DAqXTzhF6GKaQ==","Date":"Wed, 22 Apr 2026 16:25:24 -0700","Subject":"[PATCH 07/10] fuse4fs: enable safe service mode","From":"\"Darrick J. Wong\" <djwong@kernel.org>","To":"tytso@mit.edu","Cc":"linux-fsdevel@vger.kernel.org, fuse-devel@lists.linux.dev,\n linux-ext4@vger.kernel.org, neal@gompa.dev, joannelkoong@gmail.com,\n miklos@szeredi.hu, bernd@bsbernd.com","Message-ID":"<177689989662.3821326.17747399801399376401.stgit@frogsfrogsfrogs>","In-Reply-To":"<177689989498.3821326.15497525132012299039.stgit@frogsfrogsfrogs>","References":"<177689989498.3821326.15497525132012299039.stgit@frogsfrogsfrogs>","Precedence":"bulk","X-Mailing-List":"linux-ext4@vger.kernel.org","List-Id":"<linux-ext4.vger.kernel.org>","List-Subscribe":"<mailto:linux-ext4+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-ext4+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","X-Spam-Status":"No, score=-1.2 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DMARC_PASS,\n\tMAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=disabled\n\tversion=4.0.1","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org"},"content":"From: Darrick J. Wong <djwong@kernel.org>\n\nMake it possible to run fuse4fs as a safe systemd service, wherein the\nfuse server only has access to the fds that we pass in.\n\nSigned-off-by: \"Darrick J. Wong\" <djwong@kernel.org>\n---\n MCONFIG.in                  |    2 \n configure                   |  186 +++++++++++++++++++++++++++++++++\n configure.ac                |  108 +++++++++++++++++++\n fuse4fs/Makefile.in         |   40 ++++++-\n fuse4fs/fuse4fs.c           |  241 +++++++++++++++++++++++++++++++++++++++++--\n fuse4fs/fuse4fs.socket.in   |   17 +++\n fuse4fs/fuse4fs@.service.in |  102 ++++++++++++++++++\n lib/config.h.in             |    6 +\n util/subst.conf.in          |    3 +\n 9 files changed, 690 insertions(+), 15 deletions(-)\n create mode 100644 fuse4fs/fuse4fs.socket.in\n create mode 100644 fuse4fs/fuse4fs@.service.in","diff":"diff --git a/MCONFIG.in b/MCONFIG.in\nindex d66e2f3bc1d552..7a17778b6da67f 100644\n--- a/MCONFIG.in\n+++ b/MCONFIG.in\n@@ -42,6 +42,8 @@ HAVE_CROND = @have_crond@\n CROND_DIR = @crond_dir@\n HAVE_SYSTEMD = @have_systemd@\n SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@\n+HAVE_FUSE_SERVICE = @have_fuse_service@\n+HAVE_FUSE4FS_SERVICE = @have_fuse4fs_service@\n \n @SET_MAKE@\n \ndiff --git a/configure b/configure\nindex 59413d5fc32e83..0d49ec854a92cf 100755\n--- a/configure\n+++ b/configure\n@@ -645,6 +645,7 @@ enable_year2038=no\n ac_subst_vars='LTLIBOBJS\n LIBOBJS\n OS_IO_FILE\n+have_fuse4fs_service\n systemd_system_unit_dir\n have_systemd\n systemd_LIBS\n@@ -697,6 +698,9 @@ UNI_DIFF_OPTS\n SEM_INIT_LIB\n FUSE4FS_CMT\n FUSE2FS_CMT\n+fuse_service_socket_perms\n+fuse_service_socket_dir\n+have_fuse_service\n FUSE_LIB\n fuse3_LIBS\n fuse3_CFLAGS\n@@ -929,6 +933,8 @@ with_libiconv_prefix\n with_libintl_prefix\n enable_largefile\n with_libarchive\n+with_fuse_service_socket_dir\n+with_fuse_service_socket_perms\n enable_fuse2fs\n enable_fuse4fs\n enable_lto\n@@ -1652,6 +1658,11 @@ Optional Packages:\n   --with-libintl-prefix[=DIR]  search for libintl in DIR/include and DIR/lib\n   --without-libintl-prefix     don't search for libintl in includedir and libdir\n   --without-libarchive    disable use of libarchive\n+  --with-fuse-service-socket-dir[=DIR]\n+                          Create fuse3 filesystem service sockets in DIR.\n+  --with-fuse-service-socket-perms[=MODE]\n+                          Create fuse3 filesystem service socket with these\n+                          permissions.\n   --with-multiarch=ARCH   specify the multiarch triplet\n   --with-udev-rules-dir[=DIR]\n                           Install udev rules into DIR.\n@@ -14592,7 +14603,7 @@ else\n         fuse3_LIBS=$pkg_cv_fuse3_LIBS\n         { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n printf \"%s\\n\" \"yes\" >&6; }\n-        FUSE_LIB=-lfuse3\n+        FUSE_LIB=-lfuse3 ; have_fuse3_pkg=yes\n fi\n \n \n@@ -14674,6 +14685,155 @@ printf \"%s\\n\" \"#define HAVE_FUSE_LOWLEVEL 1\" >>confdefs.h\n \n fi\n \n+have_fuse_service=\n+fuse_service_socket_dir=\n+if test -n \"$have_fuse_lowlevel\"\n+then\n+\n+# Check whether --with-fuse_service_socket_dir was given.\n+if test ${with_fuse_service_socket_dir+y}\n+then :\n+  withval=$with_fuse_service_socket_dir;\n+else case e in #(\n+  e) with_fuse_service_socket_dir=yes ;;\n+esac\n+fi\n+\n+\tif test \"x${with_fuse_service_socket_dir}\" != \"xno\"\n+then :\n+\n+\t\tif test \"x${with_fuse_service_socket_dir}\" = \"xyes\"\n+then :\n+\n+\t\t\tif test \"x$have_fuse3_pkg\" = \"xyes\"\n+then :\n+\n+\t\t\t\twith_fuse_service_socket_dir=\"$($PKG_CONFIG --variable=service_socket_dir fuse3)\"\n+\n+else case e in #(\n+  e)\n+\t\t\t\twith_fuse_service_socket_dir=\"\"\n+\t\t\t   ;;\n+esac\n+fi\n+\n+fi\n+\t\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for fuse3 service socket dir\" >&5\n+printf %s \"checking for fuse3 service socket dir... \" >&6; }\n+\t\tfuse_service_socket_dir=\"${with_fuse_service_socket_dir}\"\n+\t\tif test -n \"${fuse_service_socket_dir}\"\n+then :\n+\n+\t\t\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: ${fuse_service_socket_dir}\" >&5\n+printf \"%s\\n\" \"${fuse_service_socket_dir}\" >&6; }\n+\n+else case e in #(\n+  e)\n+\t\t\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n+printf \"%s\\n\" \"no\" >&6; }\n+\t\t   ;;\n+esac\n+fi\n+\n+fi\n+\n+# Check whether --with-fuse_service_socket_perms was given.\n+if test ${with_fuse_service_socket_perms+y}\n+then :\n+  withval=$with_fuse_service_socket_perms;\n+else case e in #(\n+  e) with_fuse_service_socket_perms=yes ;;\n+esac\n+fi\n+\n+\tif test \"x${with_fuse_service_socket_perms}\" != \"xno\"\n+then :\n+\n+\t\tif test \"x${with_fuse_service_socket_perms}\" = \"xyes\"\n+then :\n+\n+\t\t\tif test \"x$have_fuse3_pkg\" = \"xyes\"\n+then :\n+\n+\t\t\t\twith_fuse_service_socket_perms=\"$($PKG_CONFIG --variable=service_socket_perms fuse3)\"\n+\n+else case e in #(\n+  e)\n+\t\t\t\twith_fuse_service_socket_perms=\"\"\n+\t\t\t   ;;\n+esac\n+fi\n+\n+fi\n+\t\tfuse_service_socket_perms=\"${with_fuse_service_socket_perms}\"\n+\n+fi\n+fi\n+if test -n \"$FUSE_USE_VERSION\"\n+then\n+\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for fuse_service_accept in libfuse\" >&5\n+printf %s \"checking for fuse_service_accept in libfuse... \" >&6; }\n+\tcat confdefs.h - <<_ACEOF >conftest.$ac_ext\n+/* end confdefs.h.  */\n+\n+\t#define _GNU_SOURCE\n+\t#define _FILE_OFFSET_BITS\t64\n+\t#define FUSE_USE_VERSION\t319\n+\t#include <fuse_lowlevel.h>\n+\t#include <fuse_service.h>\n+\n+int\n+main (void)\n+{\n+\n+\tstruct fuse_service *moo;\n+\tfuse_service_accepted(moo);\n+\n+  ;\n+  return 0;\n+}\n+\n+_ACEOF\n+if ac_fn_c_try_link \"$LINENO\"\n+then :\n+  have_fuse_service_accept=yes\n+\t   { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n+printf \"%s\\n\" \"yes\" >&6; }\n+else case e in #(\n+  e) { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n+printf \"%s\\n\" \"no\" >&6; } ;;\n+esac\n+fi\n+rm -f core conftest.err conftest.$ac_objext conftest.beam \\\n+    conftest$ac_exeext conftest.$ac_ext\n+\n+\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for fuse3 service support\" >&5\n+printf %s \"checking for fuse3 service support... \" >&6; }\n+\tif test -n \"${fuse_service_socket_dir}\" && test \"${have_fuse_service_accept}\" = \"yes\"\n+then :\n+\n+\t\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n+printf \"%s\\n\" \"yes\" >&6; }\n+\t\thave_fuse_service=\"yes\"\n+\n+else case e in #(\n+  e)\n+\t\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n+printf \"%s\\n\" \"no\" >&6; }\n+\t   ;;\n+esac\n+fi\n+fi\n+\n+\n+\n+if test \"$have_fuse_service\" = yes\n+then\n+\n+printf \"%s\\n\" \"#define HAVE_FUSE_SERVICE 1\" >>confdefs.h\n+\n+fi\n+\n FUSE2FS_CMT=\n # Check whether --enable-fuse2fs was given.\n if test ${enable_fuse2fs+y}\n@@ -16587,6 +16747,30 @@ esac\n fi\n \n \n+\n+{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for fuse4fs service support and systemd\" >&5\n+printf %s \"checking for fuse4fs service support and systemd... \" >&6; }\n+if test \"${FUSE4FS_CMT}${have_fuse_service}${have_systemd}\" = \"yesyes\"\n+then :\n+\n+           { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n+printf \"%s\\n\" \"yes\" >&6; }\n+\n+printf \"%s\\n\" \"#define HAVE_FUSE4FS_SERVICE 1\" >>confdefs.h\n+\n+           have_fuse4fs_service=yes\n+\n+else case e in #(\n+  e)\n+           { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n+printf \"%s\\n\" \"no\" >&6; }\n+           have_fuse4fs_service=no\n+\n+ ;;\n+esac\n+fi\n+\n+\n OS_IO_FILE=\"\"\n case \"$host_os\" in\n   mingw*)\ndiff --git a/configure.ac b/configure.ac\nindex c7d18dd9988db4..4b66296764ec86 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -1375,7 +1375,7 @@ dnl Check to see if the FUSE library is -lfuse3 or -losxfuse\n dnl\n FUSE_LIB=\n dnl osxfuse.dylib supersedes fuselib.dylib\n-PKG_CHECK_MODULES([fuse3], [fuse3], [FUSE_LIB=-lfuse3],\n+PKG_CHECK_MODULES([fuse3], [fuse3], [FUSE_LIB=-lfuse3 ; have_fuse3_pkg=yes],\n [\n \tAC_CHECK_LIB(osxfuse, fuse_main, [FUSE_LIB=-losxfuse])\n ])\n@@ -1427,6 +1427,96 @@ then\n \t\t  [Define to 1 if fuse supports lowlevel API])\n fi\n \n+dnl\n+dnl Check if the FUSE library tells us where to put fs service sockets\n+dnl\n+have_fuse_service=\n+fuse_service_socket_dir=\n+if test -n \"$have_fuse_lowlevel\"\n+then\n+\tAC_ARG_WITH([fuse_service_socket_dir],\n+\t  [AS_HELP_STRING([--with-fuse-service-socket-dir@<:@=DIR@:>@],\n+\t\t  [Create fuse3 filesystem service sockets in DIR.])],\n+\t  [],\n+\t  [with_fuse_service_socket_dir=yes])\n+\tAS_IF([test \"x${with_fuse_service_socket_dir}\" != \"xno\"],\n+\t  [\n+\t\tAS_IF([test \"x${with_fuse_service_socket_dir}\" = \"xyes\"],\n+\t\t  [\n+\t\t\tAS_IF([test \"x$have_fuse3_pkg\" = \"xyes\" ],\n+\t\t\t  [\n+\t\t\t\twith_fuse_service_socket_dir=\"$($PKG_CONFIG --variable=service_socket_dir fuse3)\"\n+\t\t\t  ], [\n+\t\t\t\twith_fuse_service_socket_dir=\"\"\n+\t\t\t  ])\n+\t\t  ])\n+\t\tAC_MSG_CHECKING([for fuse3 service socket dir])\n+\t\tfuse_service_socket_dir=\"${with_fuse_service_socket_dir}\"\n+\t\tAS_IF([test -n \"${fuse_service_socket_dir}\"],\n+\t\t  [\n+\t\t\tAC_MSG_RESULT(${fuse_service_socket_dir})\n+\t\t  ],\n+\t\t  [\n+\t\t\tAC_MSG_RESULT(no)\n+\t\t  ])\n+\t  ],\n+\t  [])\n+\tAC_ARG_WITH([fuse_service_socket_perms],\n+\t  [AS_HELP_STRING([--with-fuse-service-socket-perms@<:@=MODE@:>@],\n+\t\t  [Create fuse3 filesystem service socket with these permissions.])],\n+\t  [],\n+\t  [with_fuse_service_socket_perms=yes])\n+\tAS_IF([test \"x${with_fuse_service_socket_perms}\" != \"xno\"],\n+\t  [\n+\t\tAS_IF([test \"x${with_fuse_service_socket_perms}\" = \"xyes\"],\n+\t\t  [\n+\t\t\tAS_IF([test \"x$have_fuse3_pkg\" = \"xyes\" ],\n+\t\t\t  [\n+\t\t\t\twith_fuse_service_socket_perms=\"$($PKG_CONFIG --variable=service_socket_perms fuse3)\"\n+\t\t\t  ], [\n+\t\t\t\twith_fuse_service_socket_perms=\"\"\n+\t\t\t  ])\n+\t\t  ])\n+\t\tfuse_service_socket_perms=\"${with_fuse_service_socket_perms}\"\n+\t  ],\n+\t  [])\n+fi\n+if test -n \"$FUSE_USE_VERSION\"\n+then\n+\tAC_MSG_CHECKING(for fuse_service_accept in libfuse)\n+\tAC_LINK_IFELSE(\n+\t[\tAC_LANG_PROGRAM([[\n+\t#define _GNU_SOURCE\n+\t#define _FILE_OFFSET_BITS\t64\n+\t#define FUSE_USE_VERSION\t319\n+\t#include <fuse_lowlevel.h>\n+\t#include <fuse_service.h>\n+\t\t]], [[\n+\tstruct fuse_service *moo;\n+\tfuse_service_accepted(moo);\n+\t\t]])\n+\t], have_fuse_service_accept=yes\n+\t   AC_MSG_RESULT(yes),\n+\t   AC_MSG_RESULT(no))\n+\n+\tAC_MSG_CHECKING([for fuse3 service support])\n+\tAS_IF([test -n \"${fuse_service_socket_dir}\" && test \"${have_fuse_service_accept}\" = \"yes\"],\n+\t  [\n+\t\tAC_MSG_RESULT(yes)\n+\t\thave_fuse_service=\"yes\"\n+\t  ],\n+\t  [\n+\t\tAC_MSG_RESULT(no)\n+\t  ])\n+fi\n+AC_SUBST(have_fuse_service)\n+AC_SUBST(fuse_service_socket_dir)\n+AC_SUBST(fuse_service_socket_perms)\n+if test \"$have_fuse_service\" = yes\n+then\n+\tAC_DEFINE(HAVE_FUSE_SERVICE, 1, [Define to 1 if fuse supports service])\n+fi\n+\n dnl\n dnl Check if fuse2fs is actually built.\n dnl\n@@ -2098,6 +2188,22 @@ AS_IF([test \"x${with_systemd_unit_dir}\" != \"xno\"],\n   ])\n AC_SUBST(have_systemd)\n AC_SUBST(systemd_system_unit_dir)\n+\n+AC_MSG_CHECKING([for fuse4fs service support and systemd])\n+AS_IF([test \"${FUSE4FS_CMT}${have_fuse_service}${have_systemd}\" = \"yesyes\"],\n+      [\n+           AC_MSG_RESULT(yes)\n+           AC_DEFINE(HAVE_FUSE4FS_SERVICE, 1,\n+                     [Define to 1 if fuse4fs should be built with fuse service support])\n+           have_fuse4fs_service=yes\n+      ],\n+      [\n+           AC_MSG_RESULT(no)\n+           have_fuse4fs_service=no\n+      ]\n+)\n+AC_SUBST(have_fuse4fs_service)\n+\n dnl Adjust the compiled files if we are on windows vs everywhere else\n dnl\n OS_IO_FILE=\"\"\ndiff --git a/fuse4fs/Makefile.in b/fuse4fs/Makefile.in\nindex 9f3547c271638f..8de3fff338584c 100644\n--- a/fuse4fs/Makefile.in\n+++ b/fuse4fs/Makefile.in\n@@ -17,6 +17,13 @@ UMANPAGES=\n @FUSE4FS_CMT@UPROGS+=fuse4fs\n @FUSE4FS_CMT@UMANPAGES+=fuse4fs.1\n \n+ifeq ($(HAVE_FUSE4FS_SERVICE),yes)\n+SERVICE_FILES\t+= fuse4fs.socket fuse4fs@.service\n+INSTALLDIRS_TGT\t+= installdirs-systemd\n+INSTALL_TGT\t+= install-systemd\n+UNINSTALL_TGT\t+= uninstall-systemd\n+endif\n+\n FUSE4FS_OBJS=\tfuse4fs.o journal.o recovery.o revoke.o\n \n PROFILED_FUSE4FS_OJBS=\tprofiled/fuse4fs.o profiled/journal.o \\\n@@ -54,7 +61,7 @@ DEPEND_CFLAGS = -I$(top_srcdir)/e2fsck\n @PROFILE_CMT@\t$(Q) $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<\n \n all:: profiled $(SPROGS) $(UPROGS) $(USPROGS) $(SMANPAGES) $(UMANPAGES) \\\n-\t$(FMANPAGES) $(LPROGS)\n+\t$(FMANPAGES) $(LPROGS) $(SERVICE_FILES)\n \n all-static::\n \n@@ -71,6 +78,14 @@ fuse4fs: $(FUSE4FS_OBJS) $(DEPLIBS) $(DEPLIBBLKID) $(DEPLIBUUID) \\\n \t\t$(LIBFUSE) $(LIBBLKID) $(LIBUUID) $(LIBEXT2FS) $(LIBINTL) \\\n \t\t$(CLOCK_GETTIME_LIB) $(SYSLIBS) $(LIBS_E2P)\n \n+%.socket: %.socket.in $(DEP_SUBSTITUTE)\n+\t$(E) \"\tSUBST $@\"\n+\t$(Q) $(SUBSTITUTE_UPTIME) $< $@\n+\n+%.service: %.service.in $(DEP_SUBSTITUTE)\n+\t$(E) \"\tSUBST $@\"\n+\t$(Q) $(SUBSTITUTE_UPTIME) $< $@\n+\n journal.o: $(srcdir)/../debugfs/journal.c\n \t$(E) \"\tCC $<\"\n \t$(Q) $(CC) -c $(JOURNAL_CFLAGS) -I$(srcdir) \\\n@@ -93,11 +108,15 @@ fuse4fs.1: $(DEP_SUBSTITUTE) $(srcdir)/fuse4fs.1.in\n \t$(E) \"\tSUBST $@\"\n \t$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/fuse4fs.1.in fuse4fs.1\n \n-installdirs:\n+installdirs: $(INSTALLDIRS_TGT)\n \t$(E) \"\tMKDIR_P $(bindir) $(man1dir)\"\n \t$(Q) $(MKDIR_P) $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir)\n \n-install: all $(UMANPAGES) installdirs\n+installdirs-systemd:\n+\t$(E) \"\tMKDIR_P $(SYSTEMD_SYSTEM_UNIT_DIR)\"\n+\t$(Q) $(MKDIR_P) $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR)\n+\n+install: all $(UMANPAGES) installdirs $(INSTALL_TGT)\n \t$(Q) for i in $(UPROGS); do \\\n \t\t$(ES) \"\tINSTALL $(bindir)/$$i\"; \\\n \t\t$(INSTALL_PROGRAM) $$i $(DESTDIR)$(bindir)/$$i; \\\n@@ -110,13 +129,19 @@ install: all $(UMANPAGES) installdirs\n \t\t$(INSTALL_DATA) $$i $(DESTDIR)$(man1dir)/$$i; \\\n \tdone\n \n+install-systemd: $(SERVICE_FILES) installdirs-systemd\n+\t$(Q) for i in $(SERVICE_FILES); do \\\n+\t\t$(ES) \"\tINSTALL_DATA $(SYSTEMD_SYSTEM_UNIT_DIR)/$$i\"; \\\n+\t\t$(INSTALL_DATA) $$i $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR)/$$i; \\\n+\tdone\n+\n install-strip: install\n \t$(Q) for i in $(UPROGS); do \\\n \t\t$(E) \"\tSTRIP $(bindir)/$$i\"; \\\n \t\t$(STRIP) $(DESTDIR)$(bindir)/$$i; \\\n \tdone\n \n-uninstall:\n+uninstall: $(UNINSTALL_TGT)\n \tfor i in $(UPROGS); do \\\n \t\t$(RM) -f $(DESTDIR)$(bindir)/$$i; \\\n \tdone\n@@ -124,9 +149,16 @@ uninstall:\n \t\t$(RM) -f $(DESTDIR)$(man1dir)/$$i; \\\n \tdone\n \n+uninstall-systemd:\n+\tfor i in $(SERVICE_FILES); do \\\n+\t\t$(RM) -f $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR)/$$i; \\\n+\tdone\n+\n clean::\n \t$(RM) -f $(UPROGS) $(UMANPAGES) profile.h \\\n \t\tfuse4fs.profiled \\\n+\t\t$(SERVICE_FILES) \\\n+\t\tfuse4fs.socket \\\n \t\tprofiled/*.o \\#* *.s *.o *.a *~ core gmon.out\n \n mostlyclean: clean\ndiff --git a/fuse4fs/fuse4fs.c b/fuse4fs/fuse4fs.c\nindex 1203f074ac29b6..47cac88c46cea9 100644\n--- a/fuse4fs/fuse4fs.c\n+++ b/fuse4fs/fuse4fs.c\n@@ -42,6 +42,10 @@\n # define _FILE_OFFSET_BITS 64\n #endif /* _FILE_OFFSET_BITS */\n #include <fuse_lowlevel.h>\n+#ifdef HAVE_FUSE4FS_SERVICE\n+# include <sys/mount.h>\n+# include <fuse_service.h>\n+#endif\n #ifdef __SET_FOB_FOR_FUSE\n # undef _FILE_OFFSET_BITS\n #endif /* __SET_FOB_FOR_FUSE */\n@@ -122,6 +126,10 @@\n \n #define FUSE4FS_ATTR_TIMEOUT\t(0.0)\n \n+#ifndef O_DIRECT\n+# define O_DIRECT\t(0)\n+#endif\n+\n static inline uint64_t round_up(uint64_t b, unsigned int align)\n {\n \tunsigned int m;\n@@ -267,8 +275,21 @@ struct fuse4fs {\n #endif\n \tstruct fuse_session *fuse;\n \tstruct cache inodes;\n+#ifdef HAVE_FUSE4FS_SERVICE\n+\tstruct fuse_service *service;\n+\tint bdev_fd;\n+#endif\n };\n \n+#ifdef HAVE_FUSE4FS_SERVICE\n+static inline bool fuse4fs_is_service(const struct fuse4fs *ff)\n+{\n+\treturn fuse_service_accepted(ff->service);\n+}\n+#else\n+# define fuse4fs_is_service(...)\t\t(false)\n+#endif\n+\n #define FUSE4FS_CHECK_HANDLE(req, fh) \\\n \tdo { \\\n \t\tif ((fh) == NULL || (fh)->magic != FUSE4FS_FILE_MAGIC) { \\\n@@ -1231,6 +1252,105 @@ static errcode_t fuse4fs_check_support(struct fuse4fs *ff)\n \treturn 0;\n }\n \n+#ifdef HAVE_FUSE4FS_SERVICE\n+static int fuse4fs_service_connect(struct fuse4fs *ff, struct fuse_args *args)\n+{\n+\tint ret;\n+\n+\tret = fuse_service_accept(&ff->service);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!fuse4fs_is_service(ff))\n+\t\treturn 0;\n+\n+\treturn fuse_service_append_args(ff->service, args);\n+}\n+\n+static bool fuse4fs_service_should_drop_kernel_mode(const struct fuse4fs *ff)\n+{\n+\treturn ff->kernel && fuse4fs_is_service(ff) &&\n+\t       !fuse_service_can_allow_other(ff->service);\n+}\n+\n+static void fuse4fs_service_close_bdev(struct fuse4fs *ff)\n+{\n+\tif (ff->bdev_fd >= 0)\n+\t\tclose(ff->bdev_fd);\n+\tff->bdev_fd = -1;\n+}\n+\n+static int fuse4fs_service_exit(struct fuse4fs *ff, int exitcode)\n+{\n+\tif (!fuse4fs_is_service(ff))\n+\t\treturn exitcode;\n+\n+\tfuse_service_send_goodbye(ff->service, exitcode);\n+\tfuse_service_release(ff->service);\n+\tclose(ff->bdev_fd);\n+\tff->bdev_fd = -1;\n+\n+\treturn fuse_service_exit(exitcode);\n+}\n+\n+static int fuse4fs_service_get_config(struct fuse4fs *ff)\n+{\n+\tdouble deadline = init_deadline(FUSE4FS_OPEN_TIMEOUT);\n+\tconst int open_flags = O_EXCL | (ff->directio ? O_DIRECT : 0);\n+\tint open_mode = O_RDWR;\n+\tint fd;\n+\tint ret;\n+\n+\tdo {\n+\t\tret = fuse_service_request_file(ff->service, ff->device,\n+\t\t\t\t\t\topen_mode | open_flags, 0, 0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = fuse_service_receive_file(ff->service, ff->device, &fd);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif ((fd == -EPERM || fd == -EACCES || fd == -EROFS) &&\n+\t\t    open_mode == O_RDWR) {\n+\t\t\t/* Try readonly, but force the loop to run once more */\n+\t\t\topen_mode = O_RDONLY;\n+\t\t\tret = 1;\n+\t\t}\n+\t} while (ret == 1 || (fd == -EBUSY && retry_before_deadline(deadline)));\n+\n+\tif (fd < 0) {\n+\t\terr_printf(ff, \"%s %s: %s.\\n\", _(\"opening device\"), ff->device,\n+\t\t\t   strerror(-fd));\n+\t\treturn -1;\n+\t}\n+\n+\tif (!ff->ro && open_mode == O_RDONLY)\n+\t\tff->ro = 1;\n+\n+\tff->bdev_fd = fd;\n+\n+\treturn fuse_service_finish_file_requests(ff->service);\n+}\n+\n+static errcode_t fuse4fs_service_openfs(struct fuse4fs *ff, char *options,\n+\t\t\t\t\tint flags)\n+{\n+\tchar path[64];\n+\n+\tsnprintf(path, sizeof(path), \"/dev/fd/%d\", ff->bdev_fd);\n+\treturn ext2fs_open2(path, options, flags, 0, 0, unixfd_io_manager,\n+\t\t\t    &ff->fs);\n+}\n+#else\n+# define fuse4fs_service_connect(...)\t\t(0)\n+# define fuse4fs_service_should_drop_kernel_mode(...)\t(false)\n+# define fuse4fs_service_close_bdev(...)\t((void)0)\n+# define fuse4fs_service_exit(fctx, ret)\t(ret)\n+# define fuse4fs_service_get_config(...)\t(EOPNOTSUPP)\n+# define fuse4fs_service_openfs(...)\t\t(EOPNOTSUPP)\n+#endif\n+\n static errcode_t fuse4fs_acquire_lockfile(struct fuse4fs *ff)\n {\n \tchar *resolved;\n@@ -1301,6 +1421,8 @@ static void fuse4fs_unmount(struct fuse4fs *ff)\n \t\t\t\t   uuid);\n \t}\n \n+\tfuse4fs_service_close_bdev(ff);\n+\n \tif (ff->lockfile)\n \t\tfuse4fs_release_lockfile(ff);\n }\n@@ -1356,8 +1478,11 @@ static errcode_t fuse4fs_open(struct fuse4fs *ff)\n \t */\n \tdeadline = init_deadline(FUSE4FS_OPEN_TIMEOUT);\n \tdo {\n-\t\terr = ext2fs_open2(ff->device, options, flags, 0, 0,\n-\t\t\t\t   unix_io_manager, &ff->fs);\n+\t\tif (fuse4fs_is_service(ff))\n+\t\t\terr = fuse4fs_service_openfs(ff, options, flags);\n+\t\telse\n+\t\t\terr = ext2fs_open2(ff->device, options, flags, 0, 0,\n+\t\t\t\t\t   unix_io_manager, &ff->fs);\n \t\tif ((err == EPERM || err == EACCES) &&\n \t\t    (!ff->ro || (flags & EXT2_FLAG_RW))) {\n \t\t\t/*\n@@ -1702,6 +1827,10 @@ static int fuse4fs_setup_logging(struct fuse4fs *ff)\n \tif (logfile)\n \t\treturn fuse4fs_capture_output(ff, logfile);\n \n+\t/* systemd already hooked us up to /dev/ttyprintk */\n+\tif (fuse4fs_is_service(ff))\n+\t\treturn 0;\n+\n \t/* in kernel mode, try to log errors to the kernel log */\n \tif (ff->kernel)\n \t\tfuse4fs_capture_output(ff, \"/dev/ttyprintk\");\n@@ -5923,14 +6052,13 @@ static const char *get_subtype(const char *argv0)\n }\n \n static void fuse4fs_compute_libfuse_args(struct fuse4fs *ff,\n-\t\t\t\t\t struct fuse_args *args,\n-\t\t\t\t\t const char *argv0)\n+\t\t\t\t\t struct fuse_args *args)\n {\n \tchar extra_args[BUFSIZ];\n \n \t/* Set up default fuse parameters */\n \tsnprintf(extra_args, BUFSIZ, \"-osubtype=%s,fsname=%s\",\n-\t\t get_subtype(argv0),\n+\t\t get_subtype(args->argv[0]),\n \t\t ff->device);\n \tif (ff->no_default_opts == 0)\n \t\tfuse_opt_add_arg(args, extra_args);\n@@ -5947,6 +6075,15 @@ static void fuse4fs_compute_libfuse_args(struct fuse4fs *ff,\n #endif\n \t}\n \n+\t/*\n+\t * If we're mounting as a systemd service but the mount helper told us\n+\t * that allow_other isn't allowed, then disable -okernel.  This mount\n+\t * option gets special consideration because it's hardcoded in the\n+\t * service unit file.\n+\t */\n+\tif (fuse4fs_service_should_drop_kernel_mode(ff))\n+\t\tff->kernel = 0;\n+\n \tif (ff->kernel) {\n \t\t/*\n \t\t * ACLs are always enforced when kernel mode is enabled, to\n@@ -6058,6 +6195,69 @@ static int fuse4fs_event_loop(struct fuse4fs *ff,\n \treturn fuse_session_loop_mt(ff->fuse, loop_config) == 0 ? 0 : 8;\n }\n \n+#ifdef HAVE_FUSE4FS_SERVICE\n+static int fuse4fs_service_main(struct fuse_args *args, struct fuse4fs *ff)\n+{\n+\tstruct fuse_cmdline_opts opts;\n+\tstruct fuse_loop_config *loop_config = NULL;\n+\tint ret;\n+\n+\t/*\n+\t * Service initialization doesn't fork or change stdout/stderr so we\n+\t * can drop the extra logfd right now.\n+\t */\n+\tif (ff->logfd >= 0)\n+\t\tclose(ff->logfd);\n+\tff->logfd = -1;\n+\n+\tret = fuse_service_parse_cmdline_opts(args, &opts);\n+\tif (ret != 0) {\n+\t\tret = 1;\n+\t\tgoto out;\n+\t}\n+\n+\tret = fuse4fs_create_session(ff, args, &opts);\n+\tif (ret || !ff->fuse)\n+\t\tgoto out_free_opts;\n+\n+\tloop_config = fuse_loop_cfg_create();\n+\tif (loop_config == NULL) {\n+\t\tret = 7;\n+\t\tgoto out_destroy_session;\n+\t}\n+\n+\tif (fuse_set_signal_handlers(ff->fuse) != 0) {\n+\t\tret = 6;\n+\t\tgoto out_loopcfg;\n+\t}\n+\n+\tret = fuse_service_session_mount(ff->service, ff->fuse, S_IFDIR, &opts);\n+\tif (ret) {\n+\t\tret = 4;\n+\t\tgoto out_signals;\n+\t}\n+\n+\tfuse_service_send_goodbye(ff->service, 0);\n+\tfuse_service_release(ff->service);\n+\n+\tret = fuse4fs_event_loop(ff, loop_config, &opts);\n+\n+out_signals:\n+\tfuse_remove_signal_handlers(ff->fuse);\n+out_loopcfg:\n+\tfuse_loop_cfg_destroy(loop_config);\n+out_destroy_session:\n+\tfuse_session_destroy(ff->fuse);\n+\tff->fuse = NULL;\n+out_free_opts:\n+\tfree(opts.mountpoint);\n+out:\n+\treturn ret;\n+}\n+#else\n+# define fuse4fs_service_main(...)\t\t(8)\n+#endif\n+\n static int fuse4fs_main(struct fuse_args *args, struct fuse4fs *ff)\n {\n \tstruct fuse_cmdline_opts opts;\n@@ -6129,18 +6329,28 @@ int main(int argc, char *argv[])\n \t\t.bfl = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER,\n \t\t.oom_score_adj = -500,\n \t\t.opstate = F4OP_WRITABLE,\n+#ifdef HAVE_FUSE4FS_SERVICE\n+\t\t.bdev_fd = -1,\n+#endif\n \t};\n \terrcode_t err;\n \tFILE *orig_stderr = stderr;\n \tint ret;\n \n+\tret = fuse4fs_service_connect(&fctx, &args);\n+\tif (ret) {\n+\t\tret = 1;\n+\t\tgoto out_exit;\n+\t}\n+\n \tret = fuse_opt_parse(&args, &fctx, fuse4fs_opts, fuse4fs_opt_proc);\n \tif (ret)\n-\t\texit(1);\n+\t\tgoto out_exit;\n \tif (fctx.device == NULL) {\n \t\tfprintf(stderr, \"Missing ext4 device/image\\n\");\n \t\tfprintf(stderr, \"See '%s -h' for usage\\n\", argv[0]);\n-\t\texit(1);\n+\t\tret = 1;\n+\t\tgoto out_exit;\n \t}\n \n \t/* /dev/sda -> sda for reporting */\n@@ -6170,6 +6380,14 @@ int main(int argc, char *argv[])\n \t\tgoto out;\n \t}\n \n+\tif (fuse4fs_is_service(&fctx)) {\n+\t\tret = fuse4fs_service_get_config(&fctx);\n+\t\tif (ret) {\n+\t\t\tret = 2;\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n \ttry_set_io_flusher(&fctx);\n \ttry_adjust_oom_score(&fctx);\n \n@@ -6225,9 +6443,12 @@ int main(int argc, char *argv[])\n \t/* Initialize generation counter */\n \tget_random_bytes(&fctx.next_generation, sizeof(unsigned int));\n \n-\tfuse4fs_compute_libfuse_args(&fctx, &args, argv[0]);\n+\tfuse4fs_compute_libfuse_args(&fctx, &args);\n \n-\tret = fuse4fs_main(&args, &fctx);\n+\tif (fuse4fs_is_service(&fctx))\n+\t\tret = fuse4fs_service_main(&args, &fctx);\n+\telse\n+\t\tret = fuse4fs_main(&args, &fctx);\n \tswitch(ret) {\n \tcase 0:\n \t\t/* success */\n@@ -6269,6 +6490,8 @@ int main(int argc, char *argv[])\n \tif (fctx.device)\n \t\tfree(fctx.device);\n \tpthread_mutex_destroy(&fctx.bfl);\n+out_exit:\n+\tret = fuse4fs_service_exit(&fctx, ret);\n \tfuse_opt_free_args(&args);\n \treturn ret;\n }\ndiff --git a/fuse4fs/fuse4fs.socket.in b/fuse4fs/fuse4fs.socket.in\nnew file mode 100644\nindex 00000000000000..99e391bcc6787e\n--- /dev/null\n+++ b/fuse4fs/fuse4fs.socket.in\n@@ -0,0 +1,17 @@\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+#\n+# Copyright (C) 2025-2026 Oracle.  All Rights Reserved.\n+# Author: Darrick J. Wong <djwong@kernel.org>\n+[Unit]\n+Description=Socket for ext4 Service\n+\n+[Socket]\n+ListenSequentialPacket=@fuse_service_socket_dir@/ext2\n+ListenSequentialPacket=@fuse_service_socket_dir@/ext3\n+ListenSequentialPacket=@fuse_service_socket_dir@/ext4\n+Accept=yes\n+SocketMode=@fuse_service_socket_perms@\n+RemoveOnStop=yes\n+\n+[Install]\n+WantedBy=sockets.target\ndiff --git a/fuse4fs/fuse4fs@.service.in b/fuse4fs/fuse4fs@.service.in\nnew file mode 100644\nindex 00000000000000..38434c383c7be3\n--- /dev/null\n+++ b/fuse4fs/fuse4fs@.service.in\n@@ -0,0 +1,102 @@\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+#\n+# Copyright (C) 2025-2026 Oracle.  All Rights Reserved.\n+# Author: Darrick J. Wong <djwong@kernel.org>\n+[Unit]\n+Description=ext4 Service\n+\n+# Don't leave failed units behind, systemd does not clean them up!\n+CollectMode=inactive-or-failed\n+\n+[Service]\n+Type=exec\n+ExecStart=@bindir@/fuse4fs -o kernel\n+\n+# Try to capture core dumps\n+LimitCORE=infinity\n+\n+SyslogIdentifier=%N\n+\n+# No realtime CPU scheduling\n+RestrictRealtime=true\n+\n+# Don't let us see anything in the regular system, and don't run as root\n+DynamicUser=true\n+ProtectSystem=strict\n+ProtectHome=true\n+PrivateTmp=true\n+PrivateDevices=true\n+PrivateUsers=true\n+\n+# No network access\n+PrivateNetwork=true\n+ProtectHostname=true\n+RestrictAddressFamilies=none\n+IPAddressDeny=any\n+\n+# Don't let the program mess with the kernel configuration at all\n+ProtectKernelLogs=true\n+ProtectKernelModules=true\n+ProtectKernelTunables=true\n+ProtectControlGroups=true\n+ProtectProc=invisible\n+RestrictNamespaces=true\n+RestrictFileSystems=\n+\n+# Hide everything in /proc, even /proc/mounts\n+ProcSubset=pid\n+\n+# Only allow the default personality Linux\n+LockPersonality=true\n+\n+# No writable memory pages\n+MemoryDenyWriteExecute=true\n+\n+# Don't let our mounts leak out to the host\n+PrivateMounts=true\n+\n+# Restrict system calls to the native arch and only enough to get things going\n+SystemCallArchitectures=native\n+SystemCallFilter=@system-service\n+SystemCallFilter=~@privileged\n+SystemCallFilter=~@resources\n+\n+SystemCallFilter=~@clock\n+SystemCallFilter=~@cpu-emulation\n+SystemCallFilter=~@debug\n+SystemCallFilter=~@module\n+SystemCallFilter=~@reboot\n+SystemCallFilter=~@swap\n+\n+SystemCallFilter=~@mount\n+\n+# libfuse io_uring wants to pin cores and memory\n+SystemCallFilter=mbind\n+SystemCallFilter=sched_setaffinity\n+\n+# Leave a breadcrumb if we get whacked by the system call filter\n+SystemCallErrorNumber=EL3RST\n+\n+# Log to the kernel dmesg, just like an in-kernel ext4 driver\n+StandardOutput=append:/dev/ttyprintk\n+StandardError=append:/dev/ttyprintk\n+\n+# Run with no capabilities at all\n+CapabilityBoundingSet=\n+AmbientCapabilities=\n+NoNewPrivileges=true\n+\n+# fuse4fs doesn't create files\n+UMask=7777\n+\n+# No access to hardware /dev files at all\n+ProtectClock=true\n+DevicePolicy=closed\n+\n+# Don't mess with set[ug]id anything.\n+RestrictSUIDSGID=true\n+\n+# Don't let OOM kills of processes in this containment group kill the whole\n+# service, because we don't want filesystem drivers to go down.\n+OOMPolicy=continue\n+OOMScoreAdjust=-1000\ndiff --git a/lib/config.h.in b/lib/config.h.in\nindex fd2520396712e8..3aa0511a329b17 100644\n--- a/lib/config.h.in\n+++ b/lib/config.h.in\n@@ -139,6 +139,9 @@\n /* Define to 1 if you have the 'ftruncate64' function. */\n #undef HAVE_FTRUNCATE64\n \n+/* Define to 1 if fuse4fs should be built with fuse service support */\n+#undef HAVE_FUSE4FS_SERVICE\n+\n /* Define to 1 if fuse supports cache_readdir */\n #undef HAVE_FUSE_CACHE_READDIR\n \n@@ -148,6 +151,9 @@\n /* Define to 1 if fuse supports lowlevel API */\n #undef HAVE_FUSE_LOWLEVEL\n \n+/* Define to 1 if fuse supports service */\n+#undef HAVE_FUSE_SERVICE\n+\n /* Define to 1 if you have the 'futimes' function. */\n #undef HAVE_FUTIMES\n \ndiff --git a/util/subst.conf.in b/util/subst.conf.in\nindex 5af5e356d46ac7..3d0ec5cc39eabd 100644\n--- a/util/subst.conf.in\n+++ b/util/subst.conf.in\n@@ -24,3 +24,6 @@ root_bindir\t\t@root_bindir@\n libdir\t\t\t@libdir@\n $exec_prefix\t\t@exec_prefix@\n pkglibexecdir\t\t@libexecdir@/e2fsprogs\n+bindir\t\t\t@bindir@\n+fuse_service_socket_dir\t@fuse_service_socket_dir@\n+fuse_service_socket_perms\t@fuse_service_socket_perms@\n","prefixes":["07/10"]}