Merge "Revert "Libfuse: merge upstream-master up to eca63dab"" into main am: 1f5d989ce4 am: cb1045f736

Original change: https://android-review.googlesource.com/c/platform/external/libfuse/+/3287154

Change-Id: I86d356dab1239fcef11c72977a776f5c3b7cd376
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.codespellrc b/.codespellrc
deleted file mode 100644
index 6bf9ccc..0000000
--- a/.codespellrc
+++ /dev/null
@@ -1,11 +0,0 @@
-[codespell]
-skip = .git,*.pdf,*.svg,AUTHORS
-
-# The following strings shouldn't actually be accepted, but they're wrongly
-# identified as words and there is currently no way to exclude them on
-# a by-line basis (https://github.com/codespell-project/codespell/pull/2400).
-# Therefore, pretend that they are correctly spelled words:
-# - alse: used in regex
-# - siz:  wanted short
-# - fiter:  variable
-ignore-words-list = alse,siz,fiter
diff --git a/.github/ISSUE_TEMPLATE/issue-report.md b/.github/ISSUE_TEMPLATE/issue-report.md
deleted file mode 100644
index 492ce0a..0000000
--- a/.github/ISSUE_TEMPLATE/issue-report.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-name: Issue report
-about: Create a report to help us improve
-title: ''
-labels: ''
-assignees: ''
-
----
-
-PLEASE READ BEFORE REPORTING AN ISSUE
-
-libfuse does not have any active, regular contributors or developers.  The current maintainer continues to apply pull requests and tries to make regular releases, but unfortunately has no capacity to do any development beyond addressing high-impact issues. When reporting bugs, please understand that unless you are including a pull request or are reporting a critical issue, you will probably not get a response.
-
-To prevent the issue tracker from being flooded with issues that no-one is intending to work on, and to give more visibility to critical issues that users should be aware of and that most urgently need attention, I will also close most bug reports once they've been inactive for a while.
-
-Please note that this isn't meant to imply that you haven't found a bug - you most likely have and I'm grateful that you took the time to report it. Unfortunately, libfuse is a purely volunteer driven project, and at the moment there simply aren't any volunteers.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 92c44a8..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
-
-version: 2
-updates:
-  - package-ecosystem: "github-actions"
-    directory: "/"
-    schedule:
-      interval: "weekly"
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
deleted file mode 100644
index ce0cd28..0000000
--- a/.github/workflows/codespell.yml
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: Codespell
-
-on:
-  push:
-    branches: [master]
-  pull_request:
-    branches: [master]
-
-permissions:
-  contents: read
-
-jobs:
-  codespell:
-    name: Check for spelling errors
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout
-        uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
-      - name: Codespell
-        uses: codespell-project/actions-codespell@94259cd8be02ad2903ba34a22d9c13de21a74461 # v2.0
diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml
deleted file mode 100644
index cff92fd..0000000
--- a/.github/workflows/pr-ci.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: 'Build & Test'
-on:
-  push:
-    branches:
-      - master
-  pull_request:
-    branches:
-      - master
-
-permissions:
-  contents: read
-
-jobs:
-  build:
-    runs-on: '${{ matrix.os }}'
-    strategy:
-      matrix:
-        os:
-          # 18.04 does not work because of ‘no_sanitize’ attribute
-          # cc1: all warnings being treated as errors
-          # - ubuntu-18.04
-          - ubuntu-latest
-    steps:
-      - name: Install dependencies (Ubuntu)
-        if: runner.os == 'Linux'
-        run: sudo apt-get update && sudo apt-get install -y clang doxygen gcc gcc-10 gcc-9 valgrind
-      - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
-      - uses: actions/setup-python@v5
-        with:
-          python-version: '3.12'
-      - run: pip install -r requirements.txt
-      - run: test/ci-build.sh
-
diff --git a/AUTHORS b/AUTHORS
index c3b2e9d..050d953 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,7 +16,6 @@
 CUSE has been written by Tejun Heo <teheo@suse.de>. Furthermore, the
 following people have contributed patches (autogenerated list):
 
-
 1c7718e7 <shirokovMartin@gmail.com>
 a1346054 <36859588+a1346054@users.noreply.github.com>
 admorgan <admorgan@morgancomputers.net>
@@ -25,14 +24,12 @@
 Alan Somers <asomers@gmail.com>
 Albert Chen <58009229+hselin-kalista-io@users.noreply.github.com>
 Albert Chen <hselin.chen@gmail.com>
-Aleksandr Mikhailov <AM5800@users.noreply.github.com>
 Alexander <aleksandr.rvachev@eltex-co.ru>
 alex <devkral@web.de>
 Alex Richman <alex@richman.io>
 Amir Goldstein <amir73il@gmail.com>
 amosonn <amosonn@gmail.com>
 Anatol Pomozov <anatol.pomozov@gmail.com>
-André Schröder <andre.schroeder@andresco.de>
 Andrew Gaul <andrew@gaul.org>
 Andrew Gaul <gaul@google.com>
 Angelo G. Del Regno <kholk11@gmail.com>
@@ -45,8 +42,6 @@
 Banglang <banglang.huang@foxmail.com>
 Baptiste Daroussin <bapt@FreeBSD.org>
 Benjamin Barenblat <bbaren@google.com>
-Bernd Schubert <bernd.schubert@fastmail.fm>
-Bernd Schubert <bschubert@ddn.com>
 Bill Zissimooulos <billziss@navimatics.com>
 Bill Zissimopoulos <billziss@navimatics.com>
 bobrofon <ifbossfor@ya.ru>
@@ -57,7 +52,6 @@
 Changli Gao <xiaosuo@gmail.com>
 Christian Menges <christian.menges@tum.de>
 Christopher Harrison <ch12@sanger.ac.uk>
-Ciaran <ciaran@hypokrites.me>
 Consus <consus@gmx.com>
 Craig Chi <craig08@users.noreply.github.com>
 Csaba Henk <csaba.henk@creo.hu>
@@ -66,12 +60,8 @@
 Dalvik Khertel <khertel@outlook.com>
 Daniel Fullmer <danielrf12@gmail.com>
 Daniel Thau <danthau@bedrocklinux.org>
-David Galeano <davidgaleano@gmail.com>
 David McNab <david@rebirthing.co.nz>
 David Sheets <sheets@alum.mit.edu>
-dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
-Dharmendra singh <dsingh@ddn.com>
-Dharmendra Singh <dsingh@ddn.com>
 divinity76 <divinity76@gmail.com>
 DrDaveD <2129743+DrDaveD@users.noreply.github.com>
 Dr. David Alan Gilbert <dgilbert@redhat.com>
@@ -88,21 +78,16 @@
 Feng Shuo <steve.shuo.feng@gmail.com>
 ferivoz <72023087+ferivoz@users.noreply.github.com>
 Feverfew <Feverfew@users.noreply.github.com>
-Fina Wilke <code@felinira.net>
 Florian Weimer <fw@deneb.enyo.de>
 Forty-Bot <Forty-Bot@users.noreply.github.com>
-Frank Dinoff <fdinoff@google.com>
 Giulio Benetti <giulio.benetti@benettiengineering.com>
 Giuseppe Scrivano <giuseppe@scrivano.org>
-Goswin von Brederlow <goswin-v-b@web.de>
 guraga <rulumasi@dodsi.com>
 HazelFZ <xfzfygz@gmail.com>
 Heiko Becker <heirecka@exherbo.org>
 Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
-HereThereBeDragons <HereThereBeDragons@users.noreply.github.com>
 Hookey <Hookey@users.noreply.github.com>
 human <human@neet.fi>
-ikbenlike <ikbenlike@users.noreply.github.com>
 Ikey Doherty <michael.i.doherty@intel.com>
 itsdeepak <deepak.sn@samsung.com>
 Jan Blumschein <jan@jan-blumschein.de>
@@ -122,19 +107,15 @@
 Junichi Uekawa <dancerj@gmail.com>
 Junichi Uekawa <dancer@netfort.gr.jp>
 Kangjing "Chaser" Huang <huangkangjing@gmail.com>
-Ken Schalk <kcs-github@xorian.net>
 Kevin Vigor <kvigor@fb.com>
 Kirill Smelkov <kirr@nexedi.com>
-Kyle Lippincott <spectral@google.com>
 Laszlo Boszormenyi (GCS) <gcs@debian.org>
 Laszlo Papp <ext-laszlo.papp@nokia.com>
 Laurent Bigonville <bigon@users.noreply.github.com>
 Lilo Huang <lilohuang@users.noreply.github.com>
 Liu Bo <liub.liubo@gmail.com>
 Li-Wen Hsu <lwhsu.github@lwhsu.org>
-lixiaokeng <63774002+lixiaokeng@users.noreply.github.com>
 lixiaokeng <lixiaokeng@huawei.com>
-Luis Henriques <luis-henrix@users.noreply.github.com>
 Madan Valluri <mvalluri@cumulus-systems.com>
 Manuel Jacob <me@manueljacob.de>
 Marcin Sulikowski <marcin.sulikowski@editshare.com>
@@ -142,11 +123,8 @@
 Martin Blanchard <tchaik@gmx.com>
 Martin Pärtel <martin.partel@gmail.com>
 Mateusz Urbańczyk <murbanczyk@qed.ai>
-Matthias Goergens <matthias.goergens@gmail.com>
-Matthias Görgens <matthias.goergens@gmail.com>
 Mattias Nissler <mnissler@chromium.org>
 maxice8 <30738253+maxice8@users.noreply.github.com>
-Maximilian Heinzler <m.heinzler@heinzler.de>
 Max Krasnyansky <maxk@kernel.org>
 Michael Forney <mforney@mforney.org>
 Michael Grigoriev <mag@luminal.org>
@@ -157,24 +135,16 @@
 Miklos Szeredi <szmi@users.noreply.github.com>
 Misono Tomohiro <misono.tm@gmail.com>
 mkmm@gmx-topmail.de <mkmm@gmx-topmail.de>
-mrdvdrm <mrdvdrm@gmail.com>
 Natanael Copa <ncopa@alpinelinux.org>
 Niels de Vos <ndevos@redhat.com>
-Nikola Petrov <73067824+Petrov22Nikola@users.noreply.github.com>
 Nikolaus Rath <Nikolaus@rath.org>
-Nozomi Miyamori <99280467+nm004@users.noreply.github.com>
 Oded Arbel <oded@geek.co.il>
 Olivier Blin <olivier.blin@softathome.com>
 pablomh <pablomh@gmail.com>
-Pedro Kaj Kjellerup Nacht <pnacht@google.com>
-Pedro Nacht <pnacht@google.com>
-Peri <peri@srdi.org>
 Peter Lemenkov <lemenkov@gmail.com>
 philmd <philmd@users.noreply.github.com>
-Pierre Labastie <pierre.labastie@neuf.fr>
 Przemyslaw Pawelczyk <przemoc@gmail.com>
 Przemysław Pawełczyk <przemoc@gmail.com>
-psykose <alice@ayaya.dev>
 Ratna_Bolla@dell.com <Ratna_Bolla@dell.com>
 Rethan <359062468@qq.con>
 Reuben Hawkins <reubenhwk@gmail.com>
@@ -188,12 +158,10 @@
 Rosen Penev <rosenp@gmail.com>
 Rostislav <rostislav@users.noreply.github.com>
 Rostislav Skudnov <rostislav@tuxera.com>
-Rudi Heitbaum <rudi@heitbaum.com>
 Sam Huffman <40582525+samh-sifive@users.noreply.github.com>
 Sam James <sam@gentoo.org>
 Sam Stuewe <halosghost@archlinux.info>
 Sangwoo Moon <swmoon00@gmail.com>
-Sarath Lakshman <sarath@couchbase.com>
 Sargun Dhillon <sargun@sargun.me>
 scosu <mpargmann@allfex.org>
 Scott Worley <scottworley@scottworley.com>
@@ -208,7 +176,6 @@
 tenzap <46226844+tenzap@users.noreply.github.com>
 therealneworld@gmail.com <therealneworld@gmail.com>
 Tobias Nießen <tniessen@users.noreply.github.com>
-Tofik Sonono <tofik.sonono@intel.com>
 Tomasz Kulasek <34129113+tkulasek@users.noreply.github.com>
 Tom Callaway <spot@fedoraproject.org>
 Tom Callaway <spotrh@gmail.com>
@@ -216,15 +183,9 @@
 userwithuid <userwithuid@gmail.com>
 Valentin Plugaru <valentin.plugaru@uni.lu>
 Vivek Goyal <vgoyal@redhat.com>
-Waldir Pimenta <waldyrious@gmail.com>
-wdlkmpx <wdlkmpx@gmail.com>
 William Woodruff <william@yossarian.net>
 Winfried Koehler <w_scan@gmx-topmail.de>
 winndows <winndows@163.com>
-Xiubo Li <xiubli@redhat.com>
-Yaroslav Halchenko <debian@onerussian.com>
-y <tofik.sonono@intel.com>
 Yuri Per <yuri@acronis.com>
-Zhansong Gao <zhsgao@hotmail.com>
 Zhiqiang Liu <liuzhiqiang26@huawei.com>
 zsugabubus <zsugabubus@users.noreply.github.com>
diff --git a/Android.bp b/Android.bp
index a561855..3ac5418 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,7 +47,7 @@
     cflags: [
         "-D_FILE_OFFSET_BITS=64",
         "-DFUSERMOUNT_DIR=\"/system/bin\"",
-        "-DFUSE_USE_VERSION=317",
+        "-DFUSE_USE_VERSION=35",
         "-Wall",
         "-Werror",
         "-Wextra",
diff --git a/ChangeLog.rst b/ChangeLog.rst
deleted file mode 100644
index cab3e81..0000000
--- a/ChangeLog.rst
+++ /dev/null
@@ -1,810 +0,0 @@
-libfuse 3.16.2 (2023-10-10)
-===========================
-
-* Various small fixes and improvements.
-
-libfuse 3.16.1 (2023-08-08)
-===========================
-
-* Readdir kernel cache can be enabled from high-level API.
-
-libfuse 3.15.1 (2023-07-05)
-===========================
-
-Future libfuse releases will be signed with `signify`_ rather than PGP (rationale_). This
-release is the last to be signed with PGP and contains the signify public key for current
-(3.15.X) and upcoming  (3.16.X) minor release cycle.
-
-.. _signify:  https://www.openbsd.org/papers/bsdcan-signify.html
-.. _rationale: https://latacora.micro.blog/2019/07/16/the-pgp-problem.html
-
-
-libfuse 3.15.0 (2023-06-09)
-===========================
-
-* Improved support for some less common systems (32 bit, alternative libcs)
-
-* Unsupported mount options are no longer silently accepted.
-
-* auto_unmount is now compatible with allow_other.
-
-
-libfuse 3.14.1 (2023-03-26)
-===========================
-
-* The extended attribute name passed to the setxattr() handler is no longer
-  truncated at the beginning (bug introduced in 3.13.0).
-  
-* As a result of the above, the additional setattr() flags introduced in 3.14 are no
-  longer available for now. They will hopefully be reintroduced in the next release.
-
-* Further improvements of configuration header handling.
-
-
-libfuse 3.14.0 (2023-02-17)
-===========================
-
-* Properly fix the header installation issue. The fix in 3.13.1 resulted
-  in conflicts with other packages.
-
-* Introduce additional setattr() flags (FORCE, KILL_SUID, KILL_SGID, FILE, KILL_PRIV,
-  OPEN, TIMES_SET)
-
-
-libfuse 3.13.1 (2023-02-03)
-===========================
-
-* Fixed an issue that resulted in errors when attempting to compile against
-  installed libfuse headers (because libc symbol versioning support was not
-  detected correctly in this case).
-
-libfuse 3.13.0 (2023-01-13)
-===========================
-
-* There is a new low-level API function `fuse_session_custom_io` that allows to implement
-  a daemon with a custom io. This can be used to create a daemon that can process incoming
-  FUSE requests to other destinations than `/dev/fuse`.
-
-* A segfault when loading custom FUSE modules has been fixed.
-
-* There is a new `fuse_notify_expire_entry` function.
-
-* A deadlock when resolving paths in the high-level API has been fixed.
-
-* libfuse can now be build explicitly for C libraries without symbol versioning support.
-
-libfuse 3.12.0 (2022-09-08)
-===========================
-
-* There is a new build parameter to specify where the SysV init script should be
-  installed.
-  
-* The *max_idle_threads* parameter has been deprecated in favor of the new max_threads*
-  parameter (which avoids the excessive overhead of creating and destructing threads).
-  Using max_threads == 1 and calling fuse_session_loop_mt() will run single threaded
-  similar to fuse_session_loop().
-
-The following changes apply when using the most recent API (-DFUSE_USE_VERSION=312,
-see `example/passthrough_hp.cc` for an example for how to usse the new API):
-
-* `struct fuse_loop_config` is now private and has to be constructed using
-  *fuse_loop_cfg_create()* and destroyed with *fuse_loop_cfg_destroy()*.  Parameters can be
-  changed using `fuse_loop_cfg_set_*()` functions.
-
-* *fuse_session_loop_mt()* now accepts `struct fuse_loop_config *` as NULL pointer.
-
-* *fuse_parse_cmdline()* now accepts a *max_threads* option.
-
-
-libfuse 3.11.0 (2022-05-02)
-===========================
-
-* Add support for flag FOPEN_NOFLUSH for avoiding flush on close.
-* Fixed returning an error condition to ioctl(2)
-
-
-libfuse 3.10.5 (2021-09-06)
-===========================
-
-* Various improvements to make unit tests more robust.
-
-
-libfuse 3.10.4 (2021-06-09)
-===========================
-
-* Building of unit tests is now optional.
-* Fixed a test failure when running tests under XFS.
-* Fixed memory leaks in examples.
-* Minor documentation fixes.  
-
-libfuse 3.10.3 (2021-04-12)
-===========================
-
-* Fix returning d_ino and d_type from readdir(3) in non-plus mode
-  
-libfuse 3.10.2 (2021-02-05)
-===========================
-
-* Allow "nonempty" as a mount option, for backwards compatibility with fusermount 2. The
-  option has no effect since mounting over non-empty directories is allowed by default.
-* Fix returning inode numbers from readdir() in offset==0 mode.
-* FUSE filesystems can now be mounted underneath EXFAT mountpoints.
-* Various minor bugfixes.  
-
-libfuse 3.10.1 (2020-12-07)
-===========================
-
-* Various minor bugfixes.
-
-libfuse 3.10.0 (2020-10-09)
-===========================
-
-* Add FUSE_CAP_CACHE_SYMLINKS: allow caching symlinks in kernel page cache.
-* Various minor bugfixes and improvements.  
-
-libfuse 3.9.4 (2020-08-09)
-==========================
-
-This was an "accidental" release, it is equivalent to 3.9.3.
-
-libfuse 3.9.3 (2020-08-09)
-==========================
-
-* Fixed compilation under OS X and µClibc.
-* Minor bugfixes and doc updates.
-
-libfuse 3.9.2 (2020-06-12)
-==========================
-
-* Remove obsolete workarounds in examples.
-* Do not require C++ compiler for building.
-* Minor bugfixes.
-
-libfuse 3.9.1 (2020-03-19)
-===========================
-
-* Fixed memory leak in fuse_session_new().
-* Fixed an issue with the linker version script.
-* Make ioctl prototype conditional on FUSE_USE_VERSION.  Define FUSE_USE_VERSION < 35 to
-  get old ioctl prototype with int commands; define FUSE_USE_VERSION >= 35 to get new
-  ioctl prototype with unsigned int commands.
-* Various small bugfixes.
-
-libfuse 3.9.0 (2019-12-14)
-==========================
-
-* Added support for FUSE_EXPLICIT_INVAL_DATA to enable
-  only invalidate cached pages on explicit request.
-
-libfuse 3.8.0 (2019-11-03)
-==========================
-
-* Added support for FUSE_LSEEK operation which can be used to report holes
-  in sparse files.
-
-libfuse 3.7.0 (2019-09-27)
-==========================
-
-* Added UFSD to whitelist (so users can now mount FUSE filesystems
-  on mountpoints within UFSD filesystems).
-* Added custom log message handler function support so that libfuse
-  applications can direct messages to syslog(3) or other logging systems.
-  stderr remains the default.  See `fuse_log.h` for the new API.
-
-libfuse 3.6.2 (2019-07-09)
-==========================
-
-* The init script is now installed to /etc/ rather than /usr/local/etc
-  by default.
-
-libfuse 3.6.1 (2019-06-13)
-==========================
-
-* Fixed version number (release 3.6.0 was shipped with a declared
-  version of 3.0.0).
-
-libfuse 3.6.0 (2019-06-13)
-==========================
-
-* Added a new example (passthrough_hp). The functionality is similar
-  to passthrough_ll, but the implementation focuses on performance and
-  correctness rather than simplicity.
-* Added support for fuse kernel feature `max_pages` which allows to increase
-  the maximum number of pages that can be used per request. This feature was
-  introduced in kernel 4.20. `max_pages` is set based on the value in
-  `max_write`. By default `max_write` will be 1MiB now for kernels that support
-  `max_pages`. If you want smaller buffers or writes you have to set
-  `max_write` manually.
-
-libfuse 3.5.0 (2019-04-16)
-==========================
-
-* Changed ioctl commands to "unsigned int" in order to support commands
-  which do not fit into a signed int. Commands issued by applications
-  are still truncated to 32 bits.
-* Added SMB2 to whitelist (so users can now mount FUSE filesystems
-  on mountpoints within SMB 2.0 filesystems).
-* Added a new `cache_readdir` flag to `fuse_file_info` to enable
-  caching of readdir results. Supported by kernels 4.20 and newer.
-* Add support and documentation for FUSE_CAP_NO_OPENDIR_SUPPORT.
-
-libfuse 3.4.2 (2019-03-09)
-==========================
-
-* Fixed a memory leak in `examples/passthrough_ll.c`.
-* Added OpenAFS to whitelist (so users can now mount FUSE filesystems
-  on mountpoints within OpenAFS filesystems).
-* Added HFS+ to whitelist (so users can now mount FUSE filesystems
-  on mountpoints within HFS+ filesystems).
-* Documentation improvements.
-
-libfuse 3.4.1 (2018-12-22)
-==========================
-
-* The `examples/passthrough_ll.c` example filesystem has been
-  significantly extended.
-* Support for `copy_file_range` has been added.
-* Build system updates for non-Linux systems.
-
-libfuse 3.4.0
-=============
-
-* Add `copy_file_range()` to support efficient copying of data from one file to
-  an other.
-
-libfuse 3.3.0 (2018-11-06)
-==========================
-
-* The `auto_unmount` mode now works correctly in combination with
-  autofs.
-
-* The FUSE_CAP_READDIRPLUS_AUTO capability is no longer enabled by
-  default unless the file system defines both a readdir() and a
-  readdirplus() handler.
-
-* The description of the FUSE_CAP_READDIRPLUS_AUTO flag has been
-  improved.
-
-* Allow open `/dev/fuse` file descriptors to be passed via mountpoints of the
-  special format `/dev/fd/%u`. This allows mounting to be handled by the parent
-  so the FUSE filesystem process can run fully unprivileged.
-
-* Add a `drop_privileges` option to mount.fuse3 which causes it to open
-  `/dev/fuse` and mount the file system itself, then run the FUSE file
-  filesystem fully unprivileged and unable to re-acquire privilege via setuid,
-  fscaps, etc.
-
-* Documented under which conditions the `fuse_lowlevel_notify_*`
-  functions may block.
-
-libfuse 3.2.6 (2018-08-31)
-==========================
-
-* The fuse_main() function now returns more fine-grained error codes.
-* FUSE filesystems may now be mounted on mountpoint within
-  bcachefs, aufs and FAT filesystems.
-* libfuse may now be used as a Meson subproject.
-* Fix a few low-impact memory leaks.
-* The `fuse.conf` file is no longer looked for in `/etc`, but in the
-  *sysconfdir* directory (which can be set with `meson configure`). By
-  default, the location is thus `/usr/local/etc/fuse.conf`.
-
-libfuse 3.2.5 (2018-07-24)
-==========================
-
-* SECURITY UPDATE: In previous versions of libfuse it was possible to
-  for unprivileged users to specify the `allow_other` option even when
-  this was forbidden in `/etc/fuse.conf`.  The vulnerability is
-  present only on systems where SELinux is active (including in
-  permissive mode).
-* The fusermount binary has been hardened in several ways to reduce
-  potential attack surface. Most importantly, mountpoints and mount
-  options must now match a hard-coded whitelist. It is expected that
-  this whitelist covers all regular use-cases.
-* Added a test of `seekdir` to test_syscalls.
-* Fixed `readdir` bug when non-zero offsets are given to filler and the
-  filesystem client, after reading a whole directory, re-reads it from a
-  non-zero offset e. g. by calling `seekdir` followed by `readdir`.
-
-libfuse 3.2.4 (2018-07-11)
-==========================
-
-* Fixed `rename` deadlock on FreeBSD.
-
-libfuse 3.2.3 (2018-05-11)
-==========================
-
-* Fixed a number of compiler warnings.  
-
-libfuse 3.2.2 (2018-03-31)
-==========================
-
-* Added example fuse.conf file.
-* Added "support" for -o nofail mount option (the option is accepted
-  and ignored).
-* Various small bugfixes.  
-
-libfuse 3.2.1 (2017-11-14)
-==========================
-
-* Various small bugfixes.
-
-libfuse 3.2.0 (2017-09-12)
-==========================
-
-* Support for building with autotools has been dropped.
-
-* Added new `fuse_invalidate_path()` routine for cache invalidation
-  from the high-level FUSE API, along with an example and tests.
-
-* There's a new `printcap` example that can be used to determine the
-  capabilities of the running kernel.
-
-* `fuse_loop_mt()` now returns the minus the actual errno if there was
-  an error (instead of just -1).
-
-* `fuse_loop()` no longer returns a positive value if the filesystem
-  loop was terminated without errors or signals.
-
-* Improved documentation of `fuse_lowlevel_notify_*` functions.
-
-* `fuse_lowlevel_notify_inval_inode()` and
-  `fuse_lowlevel_notify_inval_entry()` now return -ENOSYS instead of
-  an undefined error if the function is not supported by the kernel.
-
-* Documented the special meaning of the *zero* offset for the
-  fuse_fill_dir_t function.
-
-* The `passthrough_fh` example now works under FreeBSD.
-
-* libfuse can now be build without libiconv.
-
-* Fixed support for `FUSE_CAP_POSIX_ACL`: setting this capability
-  flag had no effect in the previous versions of libfuse 3.x;
-  now ACLs should actually work.
-
-* Fixed a number of compilation problems under FreeBSD.
-
-* Fixed installation directory for udev rules.
-
-* Fixed compilation with LTO.
-
-libfuse 3.1.1 (2017-08-06)
-==========================
-
-* Documentation: clarified how filesystems are supposed to process
-  open() and create() flags (see include/fuse_lowlevel.h).
-
-* Fixed a compilation problem of the passthrough_ll example on
-  32 bit systems (wrong check and wrong error message).
-
-* pkg-config is now used to determine the proper directory for
-  udev rules.
-
-* Fixed a symbol versioning problem that resulted in very strange
-  failures (segfaults, unexpected behavior) in different situations.
-
-* Fixed a test failure when /tmp is on btrfs.
-
-* The maximum number of idle worker threads used by `fuse_loop_mt()`
-  is now configurable.
-
-* `fuse_loop_mt()` and `fuse_session_loop_mt()` now take a
-  `struct fuse_loop_config` parameter that supersedes the *clone_fd*
-  parameter.
-
-* Incorporated several patches from the FreeBSD port. libfuse should
-  now compile under FreeBSD without the need for patches.
-
-* The passthrough_ll example now supports writeback caching.
-
-libfuse 3.1.0 (2017-07-08)
-==========================
-
-* Added new `fuse_lib_help()` function. File-systems that previously
-  passed a ``--help`` option to `fuse_new()` must now process the
-  ``--help`` option internally and call `fuse_lib_help()` to print the
-  help for generic FUSE options.
-* Fixed description of the `fuse_conn_info->time_gran`. The default
-  value of zero actually corresponds to full nanosecond resolution,
-  not one second resolution.
-* The init script is now installed into the right location
-  (``$DESTDIR/etc/init.d`` rather than ``$prefix/$sysconfdir/init.d``)
-* The `example/passthrough_ll` filesystem now supports creating
-  and writing to files.
-* `fuse_main()` / `fuse_remove_signal_handlers()`: do not reset
-  `SIGPIPE` handler to `SIG_DFL` if it was not set by us.
-* Documented the `RENAME_EXCHANGE` and `RENAME_NOREPLACE` flags that
-  may be passed to the `rename` handler of both the high- and
-  low-level API. Filesystem authors are strongly encouraged to check
-  that these flags are handled correctly.
-
-libfuse 3.0.2 (2017-05-24)
-==========================
-
-* Option parsing for the high-level API now works correctly
-  (previously, default values would override specified values).
-* Tests should now build (and run) under FreeBSD.
-* Improved documentation of `struct fuse_context`
-* Internal: calculate request buffer size from page size and kernel
-  page limit instead of using hardcoded 128 kB limit.
-
-
-libfuse 3.0.1 (2017-04-10)
-==========================
-
-* Re-introduced *examples/null.c*.
-* Added experimental support for building with Meson.
-* Document that `-o auto_unmount` implies `-o nodev,nosuid`.
-* Document that the *use_ino* option of the high-level interface does
-  not affect the inode that libfuse and the kernel use internally.
-* Fixed test cases for passthrough* examples (they weren't actually
-  testing the examples).
-* Fixed several bugs in the passthrough* examples.
-
-libfuse 3.0.0 (2016-12-08)
-==========================
-
-* NOTE TO PACKAGERS:
-
-  libfuse 3 is designed to be co-installable with libfuse 2. However,
-  some files will be installed by both libfuse 2 and libfuse 3
-  (e.g. /etc/fuse.conf, the udev and init scripts, and the
-  mount.fuse(8) manpage). These files should be taken from
-  libfuse 3. The format/content is guaranteed to remain backwards
-  compatible with libfuse 2.
-
-  We recommend to ship libfuse2 and libfuse3 in three separate
-  packages: a libfuse-common package that contains files shared by
-  libfuse 2+3 (taken from the libfuse3 tarball), and libfuse2 and
-  libfuse3 packages that contain the shared library and helper
-  programs for the respective version.
-
-* Fixed test errors when running tests as root.
-
-* Made check for util-linux version more robust.
-
-* Added documentation for all fuse capability flags (`FUSE_CAP_*`) and
-  `struct fuse_conn_info` fields.
-
-* fuse_loop(), fuse_loop_mt(), fuse_session_loop() and
-  fuse_session_loop_mt() now return more detailed error codes instead
-  of just -1. See the documentation of fuse_session_loop() for details.
-
-* The FUSE main loop is now aborted if the file-system requests
-  capabilities that are not supported by the kernel. In this case, the
-  session loop is exited with a return code of ``-EPROTO``.
-
-* Most file-system capabilities that were opt-in in libfuse2 are now
-  enabled by default. Filesystem developers are encouraged to review
-  the documentation of the FUSE_CAP_* features to ensure that their
-  filesystem is compatible with the new semantics. As before, a
-  particular capability can still be disabled by unsetting the
-  corresponding bit of `fuse_conn_info.wants` in the init() handler.
-
-* Added FUSE_CAP_PARALLEL_DIROPS and FUSE_CAP_POSIX_ACL,
-  FUSE_HANDLE_KILLPRIV feature flags.
-
-* FUSE filesystems are now responsible for unsetting the setuid/setgid
-  flags when a file is written, truncated, or its owner
-  changed. Previously, this was handled by the kernel but subject to
-  race conditions.
-
-* The fusermount and mount.fuse binaries have been renamed to
-  fusermount3 and mount.fuse3 to allow co-installation of libfuse 2.x
-  and 3.x
-
-* Added a `max_read` field to `struct fuse_conn_info`. For the time
-  being, the maximum size of read requests has to be specified both
-  there *and* passed to fuse_session_new() using the ``-o
-  max_read=<n>`` mount option. At some point in the future, specifying
-  the mount option will no longer be necessary.
-
-* Documentation: clarified that the fuse_argv structure that is passed
-  to `fuse_new()` and `fuse_lowlevel_new()` must always contain at
-  least one element.
-
-* The high-level init() handler now receives an additional struct
-  fuse_config pointer that can be used to adjust high-level API
-  specific configuration options.
-
-* The `nopath_flag` field of struct fuse_operations has been
-  removed. Instead, a new `nullpath_ok` flag can now be set
-  in struct fuse_config.
-
-* File systems that use the low-level API and support lookup requests
-  for '.' and '..' should continue make sure to set the
-  FUSE_CAP_EXPORT_SUPPORT bit in fuse_conn_info->want.
-
-  (This has actually always been the case, but was not very obvious
-  from the documentation).
-
-* The help text generated by fuse_lowlevel_help(), fuse_new() (and
-  indirectly fuse_main()) no longer includes options that are unlikely
-  to be of interest to end-users. The full list of accepted options is
-  now included in the respective function's documentation (located in
-  the fuse.h/fuse_lowlevel.h and doc/html).
-
-* The ``-o nopath`` option has been dropped - it never actually did
-  anything (since it is unconditionally overwritten with the value of
-  the `nopath` flag in `struct fuse_operations`).
-
-* The ``-o large_read`` mount option has been dropped. Hopefully no
-  one uses a Linux 2.4 kernel anymore.
-
-* The `-o nonempty` mount point has been removed, mounting over
-  non-empty directories is now always allowed. This brings the
-  behavior of FUSE file systems in-line with the behavior of the
-  regular `mount` command.
-
-  File systems that do not want to allow mounting to non-empty
-  directories should perform this check themselves before handing
-  control to libfuse.
-
-* The chmod, chown, truncate, utimens and getattr handlers of the
-  high-level API now all receive an additional struct fuse_file_info
-  pointer (which, however, may be NULL even if the file is currently
-  open).
-
-  The fgetattr and ftruncate handlers have become obsolete and have
-  been removed.
-
-* The `fuse_session_new` function no longer accepts the ``-o
-  clone_fd`` option. Instead, this has become a parameter of the
-  `fuse_session_loop_mt` and `fuse_loop_mt` functions.
-
-* For low-level file systems that implement the `write_buf` handler,
-  the `splice_read` option is now enabled by default. As usual, this
-  can be changed in the file system's `init` handler.
-
-* The treatment of low-level options has been made more consistent:
-
-  Options that can be set in the init() handler (via the
-  fuse_conn_info parameter) can now be set only here,
-  i.e. fuse_session_new() no longer accepts arguments that change the
-  fuse_conn_info object before or after the call do init(). As a side
-  effect, this removes the ambiguity where some options can be
-  overwritten by init(), while others overwrite the choices made by
-  init().
-
-  For file systems that wish to offer command line options for these
-  settings, the new fuse_parse_conn_info_opts() and
-  fuse_apply_conn_info_opts() functions are available.
-
-  Consequently, the fuse_lowlevel_help() method has been dropped.
-
-* The `async_read` field in `struct fuse_conn_info` has been
-  removed. To determine if the kernel supports asynchronous reads,
-  file systems should check the `FUSE_CAP_ASYNC_READ` bit of the
-  `capable` field. To enable/disable asynchronous reads, file systems
-  should set the flag in the `wanted` field.
-
-* The `fuse_parse_cmdline` function no longer prints out help when the
-  ``--verbose`` or ``--help`` flags are given. This needs to be done
-  by the file system (e.g. using the `fuse_cmdline_help()` and
-  `fuse_lowlevel_help()` functions).
-
-* Added ``example/cuse_client.c`` to test ``example/cuse.c``.
-
-* Removed ``example/null.c``. This has not been working for a while
-  for unknown reasons -- maybe because it tries to treat the
-  mountpoint as a file rather than a directory?
-
-* There are several new examples that demonstrate the use of
-  the ``fuse_lowlevel_notify_*`` functions:
-
-  - ``example/notify_store_retrieve.c``
-  - ``example/notify_inval_inode.c``
-  - ``example/notify_inval_entry.c``
-
-* The ``-o big_writes`` mount option has been removed. It is now
-  always active. File systems that want to limit the size of write
-  requests should use the ``-o max_write=<N>`` option instead.
-
-* The `fuse_lowlevel_new` function has been renamed to
-  `fuse_session_new` and no longer interprets the --version or --help
-  options. To print help or version information, use the new
-  `fuse_lowlevel_help` and `fuse_lowlevel_version` functions.
-
-* The ``allow_other`` and ``allow_root`` mount options (accepted by
-  `fuse_session_new()`) may now be specified together. In this case,
-  ``allow_root`` takes precedence.
-
-* There are new `fuse_session_unmount` and `fuse_session_mount`
-  functions that should be used in the low-level API. The `fuse_mount`
-  and `fuse_unmount` functions should be used with the high-level API
-  only.
-
-* Neither `fuse_mount` nor `fuse_session_mount` take struct fuse_opts
-  parameters anymore. Mount options are parsed by `fuse_new` (for the
-  high-level API) and `fuse_session_new` (for the low-level API)
-  instead. To print help or version information, use the new
-  `fuse_mount_help` and `fuse_mount_version` functions.
-
-* The ``fuse_lowlevel_notify_*`` functions now all take a `struct
-  fuse_session` parameter instead of a `struct fuse_chan`.
-
-* The channel interface (``fuse_chan_*`` functions) has been made
-  private. As a result, the typical initialization sequence of a
-  low-level file system has changed from ::
-
-        ch = fuse_mount(mountpoint, &args);
-        se = fuse_lowlevel_new(&args, &lo_oper, sizeof(lo_oper), &lo);
-        fuse_set_signal_handlers(se);
-        fuse_session_add_chan(se, ch);
-        fuse_daemonize(fg);
-        if (mt)
-            fuse_session_loop_mt(se);
-        else
-            fuse_session_loop(se);
-        fuse_remove_signal_handlers(se);
-        fuse_session_remove_chan(ch);
-        fuse_session_destroy(se);
-        fuse_unmount(mountpoint, ch);
-
-  to ::
-
-        se = fuse_session_new(&args, &ll_ops, sizeof(ll_ops), NULL);
-        fuse_set_signal_handlers(se);
-        fuse_session_mount(se, mountpoint);
-        fuse_daemonize(fg);
-        if (mt)
-            fuse_session_loop_mt(se);
-        else
-            fuse_session_loop(se);
-        fuse_remove_signal_handlers(se);
-        fuse_session_unmount(se);
-        fuse_lowlevel_destroy(se);
-
-  The typical high-level setup has changed from ::
-
-        ch = fuse_mount(*mountpoint, &args);
-        fuse = fuse_new(ch, &args, op, op_size, user_data);
-        se = fuse_get_session(fuse);
-        fuse_set_signal_handlers(se);
-        fuse_daemonize(fg);
-        if (mt)
-            fuse_loop_mt(fuse);
-        else
-            fuse_loop(fuse);
-        fuse_remove_signal_handlers(se);
-        fuse_unmount(mountpoint, ch);
-        fuse_destroy(fuse);
-
-  to ::
-
-        fuse = fuse_new(&args, op, op_size, user_data);
-        se = fuse_get_session(fuse);
-        fuse_set_signal_handlers(se);
-        fuse_mount(fuse, mountpoint);
-        fuse_daemonize(fg);
-         if (mt)
-            fuse_loop_mt(fuse);
-        else
-            fuse_loop(fuse);
-        fuse_remove_signal_handlers(se);
-        fuse_unmount(fuse);
-        fuse_destroy(fuse);
-
-  File systems that use `fuse_main` are not affected by this change.
-
-  For integration with custom event loops, the new `fuse_session_fd`
-  function provides the file descriptor that's used for communication
-  with the kernel.
-
-* Added *clone_fd* option.  This creates a separate device file
-  descriptor for each processing thread, which might improve
-  performance.
-
-* Added *writeback_cache* option. With kernel 3.14 and newer this
-  enables write-back caching which can significantly improve
-  performance.
-
-* Added *async_dio* option. With kernel 3.13 and newer, this allows
-  direct I/O to be done asynchronously.
-
-* The (high- and low-level) `rename` handlers now takes a *flags*
-  parameter (with values corresponding to the *renameat2* system call
-  introduced in Linux 3.15).
-
-* The "ulockmgr_server" has been dropped.
-
-* There is a new (low-level) `readdirplus` handler, with a
-  corresponding example in ``examples/fuse_lo-plus.c`` and a new
-  `fuse_add_direntry_plus` API function.
-
-* The (high-level) `readdir` handler now takes a *flags* argument.
-
-* The (high-level) `filler` function passed to `readdir` now takes an
-  additional *flags* argument.
-
-* The (high-level) `getdir` handler has been dropped.
-
-* The *flag_nullpath_ok* and *flag_utime_omit_ok* flags have been
-  dropped.
-
-* The (high-level) *utime* handler has been dropped.
-
-* The `fuse_invalidate` function has been removed.
-
-* The `fuse_is_lib_option` function has been removed.
-
-* The *fh_old* member of `struct fuse_file_info` has been dropped.
-
-* The type of the *writepage* member of `struct fuse_file_info` was
-  changed from *int* to *unsigned int*.
-
-* The `struct fuse_file_info` gained a new *poll_events* member.
-
-* There is a new `fuse_pkgversion` function.
-
-* The *fuse_off_t* and *fuse_ino_t* changed from *unsigned long* to
-  *uint64_t*, i.e. they are now 64 bits also on 32-bit systems.
-
-* The type of the *generation* member of `struct fuse_entry_param*`
-  changed from *unsigned* to *uint64_t*.
-
-* The (low-level) `setattr` handler gained a *FUSE_SET_ATTR_CTIME* bit
-  *for its *to_set* parameter.
-
-* The `struct fuse_session_ops` data structure has been dropped.
-
-* The documentation has been clarified and improved in many places.
-
-
-FUSE 2.9.7 (2016-06-20)
-=======================
-
-* Added SELinux support.
-* Fixed race-condition when session is terminated right after starting
-  a FUSE file system.
-
-FUSE 2.9.6 (2016-04-23)
-=======================
-
-* Tarball now includes documentation.
-* Shared-object version has now been bumped correctly.
-
-FUSE 2.9.5 (2016-01-14)
-=======================
-
-* New maintainer: Nikolaus Rath <Nikolaus@rath.org>. Many thanks to
-  Miklos Szeredi <miklos@szeredi.hu> for bringing FUSE to where it is
-  now!
-
-* fix warning in mount.c:receive_fd().  Reported by Albert Berger
-
-* fix possible memory leak.  Reported by Jose R. Guzman
-
-FUSE 2.9.4 (2015-05-22)
-=======================
-
-* fix exec environment for mount and umount.  Found by Tavis Ormandy
-  (CVE-2015-3202).
-
-* fix fuse_remove_signal_handlers() to properly restore the default
-  signal handler.  Reported by: Chris Johnson
-
-* highlevel API: fix directory file handle passed to ioctl() method.
-  Reported by Eric Biggers
-
-* libfuse: document deadlock avoidance for fuse_notify_inval_entry()
-  and fuse_notify_delete()
-
-* fusermount, libfuse: send value as unsigned in "user_id=" and
-  "group_id=" options.  Uids/gids larger than 2147483647 would result
-  in EINVAL when mounting the filesystem.  This also needs a fix in
-  the kernel.
-
-* Initialize stat buffer passed to ->getattr() and ->fgetattr() to
-  zero in all cases.  Reported by Daniel Iwan
-
-* libfuse: Add missing includes.  This allows compiling fuse with
-  musl.  Patch by Daniel Thau
-
-
-Older Versions (before 2013-01-01)
-==================================
-
-Please see Git history, e.g. at
-https://github.com/libfuse/libfuse/blob/fuse_2_9_3/ChangeLog.
diff --git a/METADATA b/METADATA
index 5caa8fc..78a08d4 100644
--- a/METADATA
+++ b/METADATA
@@ -1,18 +1,18 @@
 name: "libfuse"
 description:
-    "The reference implementation of the Linux FUSE (Filesystem in Userspace) interface"
+    "The reference implementation of the Linux FUSE (Filesystem in Userspace) "
+    "interface"
 
 third_party {
-  license_type: RESTRICTED_IF_STATICALLY_LINKED
-  last_upgrade_date {
-    year: 2024
-    month: 7
-    day: 17
+  url {
+    type: HOMEPAGE
+    value: "https://github.com/libfuse"
   }
-  homepage: "https://github.com/libfuse"
-  identifier {
-    type: "Git"
+  url {
+    type: GIT
     value: "https://github.com/libfuse/libfuse.git"
-    version: "eca63dab456a10c3491c367711ab18cbcb34816e"
   }
+  version: "fuse-3.8.0"
+  last_upgrade_date { year: 2019 month: 11 day: 6 }
+  license_type: RESTRICTED_IF_STATICALLY_LINKED
 }
diff --git a/README.md b/README.md
index eaf1308..052effc 100644
--- a/README.md
+++ b/README.md
@@ -49,34 +49,21 @@
 Installation
 ------------
 
-You can download libfuse from https://github.com/libfuse/libfuse/releases. To build and
-install, you must use [Meson](http://mesonbuild.com/) and
-[Ninja](https://ninja-build.org).  After downloading the tarball and `.sig` file, verify
-it using [signify](https://www.openbsd.org/papers/bsdcan-signify.html):
+You can download libfuse from
+https://github.com/libfuse/libfuse/releases. To build and install, you
+must use [Meson](http://mesonbuild.com/) and
+[Ninja](https://ninja-build.org).  After extracting the libfuse
+tarball, create a (temporary) build directory and run Meson:
 
-    signify -V -m fuse-X.Y.Z.tar.gz -p fuse-X.Y.pub
-    
-The `fuse-X.Y.pub` file contains the signing key and needs to be obtained from a
-trustworthy source. Each libfuse release contains the signing key for the release after it
-in the `signify` directory, so you only need to manually acquire this file once when you
-install libfuse for the first time.
-
-After you have validated the tarball, extract it, create a (temporary) build directory and
-run Meson:
-
-    $ tar xzf fuse-X.Y.Z.tar.gz; cd fuse-X.Y.Z
     $ mkdir build; cd build
-    $ meson setup ..
+    $ meson ..
 
 Normally, the default build options will work fine. If you
 nevertheless want to adjust them, you can do so with the
 *meson configure* command:
 
     $ meson configure # list options
-    $ meson configure -D disable-mtab=true # set an optionq
-
-    $ # ensure all meson options are applied to the final build system
-    $ meson setup --reconfigure ../
+    $ meson configure -D disable-mtab=true # set an option
 
 To build, test, and install libfuse, you then use Ninja:
 
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index 19e1366..0000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Security Policy
-
-If you have discovered a security vulnerability in this project, please report it
-privately. **Do not disclose it as a public issue.** This gives me time to work with you
-to fix the issue before public exposure, reducing the chance that the exploit will be
-used before a patch is released.
-
-Please submit information on the vulnerability as a
-[private report](https://github.com/libfuse/libfuse/security/advisories/new).
-
-Please provide the following information in your report:
-
-- A description of the vulnerability and its impact
-- How to reproduce the issue
-
-This project is maintained by a single volunteer on a reasonable-effort basis. As such,
-I ask that you give me 90 days to work on a fix before public exposure.
-
-Note we are aware of a long-standing security issue when using `allow_others` (see
-[#15](https://github.com/libfuse/libfuse/issues/15)).
\ No newline at end of file
diff --git a/include/fuse.h b/include/fuse.h
index a3549cb..9e6c633 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -48,7 +48,6 @@
 	 * FUSE_FILL_DIR_FLAGS for the filler function.  The filesystem may also
 	 * just ignore this flag completely.
 	 */
-	FUSE_READDIR_DEFAULTS = 0,
 	FUSE_READDIR_PLUS = (1 << 0)
 };
 
@@ -65,7 +64,6 @@
 	 * It is okay to set FUSE_FILL_DIR_PLUS if FUSE_READDIR_PLUS is not set
 	 * and vice versa.
 	 */
-	FUSE_FILL_DIR_DEFAULTS = 0,
 	FUSE_FILL_DIR_PLUS = (1 << 1)
 };
 
@@ -250,14 +248,6 @@
 	int auto_cache;
 
 	/**
-	 * By default, fuse waits for all pending writes to complete
-	 * and calls the FLUSH operation on close(2) of every fuse fd.
-	 * With this option, wait and FLUSH are not done for read-only
-	 * fuse fd, similar to the behavior of NFS/SMB clients.
-	 */
-	int no_rofd_flush;
-
-	/**
 	 * The timeout in seconds for which file attributes are cached
 	 * for the purpose of checking if auto_cache should flush the
 	 * file data on open.
@@ -276,20 +266,6 @@
 	 * fuse_file_info argument is NULL.
 	 */
 	int nullpath_ok;
-	/**
-	 *  Allow parallel direct-io writes to operate on the same file.
-	 *
-	 *  FUSE implementations which do not handle parallel writes on
-	 *  same file/region should NOT enable this option at all as it
-	 *  might lead to data inconsistencies.
-	 *
-	 *  For the FUSE implementations which have their own mechanism
-	 *  of cache/data integrity are beneficiaries of this setting as
-	 *  it now open doors to parallel writes on the same file (without
-	 *  enabling this setting, all direct writes on the same file are
-	 *  serialized, resulting in huge data bandwidth loss).
-	 */
-	int parallel_direct_writes;
 
 	/**
 	 * The remaining options are used by libfuse internally and
@@ -456,7 +432,7 @@
 	 * If this request is answered with an error code of ENOSYS
 	 * and FUSE_CAP_NO_OPEN_SUPPORT is set in
 	 * `fuse_conn_info.capable`, this is treated as success and
-	 * future calls to open will also succeed without being sent
+	 * future calls to open will also succeed without being send
 	 * to the filesystem process.
 	 *
 	 */
@@ -579,29 +555,16 @@
 	 * passes non-zero offset to the filler function.  When the buffer
 	 * is full (or an error happens) the filler function will return
 	 * '1'.
-	 *
-	 * When FUSE_READDIR_PLUS is not set, only some parameters of the
-	 * fill function (the fuse_fill_dir_t parameter) are actually used:
-	 * The file type (which is part of stat::st_mode) is used. And if
-	 * fuse_config::use_ino is set, the inode (stat::st_ino) is also
-	 * used. The other fields are ignored when FUSE_READDIR_PLUS is not
-	 * set.
 	 */
 	int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
 			struct fuse_file_info *, enum fuse_readdir_flags);
 
 	/** Release directory
-	 *
-	 * If the directory has been removed after the call to opendir, the
-	 * path parameter will be NULL.
 	 */
 	int (*releasedir) (const char *, struct fuse_file_info *);
 
 	/** Synchronize directory contents
 	 *
-	 * If the directory has been removed after the call to opendir, the
-	 * path parameter will be NULL.
-	 *
 	 * If the datasync parameter is non-zero, then only the user data
 	 * should be flushed, not the meta data
 	 */
@@ -854,22 +817,6 @@
 	mode_t umask;
 };
 
-#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
-/**
- * The real main function
- *
- * Do not call this directly, use fuse_main()
- */
-int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
-		   size_t op_size, struct libfuse_version *version,
-		   void *user_data);
-#else
-int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
-		   size_t op_size, struct libfuse_version *version, void *user_data);
-#define fuse_main_real(argc, argv, op, op_size, version, user_data) \
-	fuse_main_real_317(argc, argv, op, op_size, version, user_data);
-#endif
-
 /**
  * Main function of FUSE.
  *
@@ -924,19 +871,12 @@
  *
  * Example usage, see hello.c
  */
-static inline int
-fuse_main(int argc, char *argv[], const struct fuse_operations *op,
-	  void *user_data)
-{
-	struct libfuse_version version = {
-		.major  = FUSE_MAJOR_VERSION,
-		.minor  = FUSE_MINOR_VERSION,
-		.hotfix = FUSE_HOTFIX_VERSION,
-		.padding = 0
-	};
-	return fuse_main_real(argc, argv, op, sizeof(*(op)), &version,
-			      user_data);
-}
+/*
+  int fuse_main(int argc, char *argv[], const struct fuse_operations *op,
+  void *private_data);
+*/
+#define fuse_main(argc, argv, op, private_data)				\
+	fuse_main_real(argc, argv, op, sizeof(*(op)), private_data)
 
 /* ----------------------------------------------------------- *
  * More detailed API					       *
@@ -955,11 +895,6 @@
  */
 void fuse_lib_help(struct fuse_args *args);
 
-struct fuse *_fuse_new(struct fuse_args *args,
-		       const struct fuse_operations *op,
-		       size_t op_size, struct libfuse_version *version,
-		       void *user_data);
-
 /**
  * Create a new FUSE filesystem.
  *
@@ -988,61 +923,12 @@
  * @return the created FUSE handle
  */
 #if FUSE_USE_VERSION == 30
-struct fuse *_fuse_new_30(struct fuse_args *args,
-			 const struct fuse_operations *op,
-			 size_t op_size, void *user_data);
-static inline struct fuse *
-fuse_new(struct fuse_args *args,
-	 const struct fuse_operations *op, size_t op_size,
-	 void *user_data)
-{
-	struct libfuse_version version = {
-		.major = FUSE_MAJOR_VERSION,
-		.minor = FUSE_MINOR_VERSION,
-		.hotfix = FUSE_HOTFIX_VERSION,
-		.padding = 0
-	};
-
-	return _fuse_new_30(args, op, op_size, &version, user_data);
-}
+struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
+			 size_t op_size, void *private_data);
+#define fuse_new(args, op, size, data) fuse_new_30(args, op, size, data)
 #else
-#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
-static inline struct fuse *
-fuse_new(struct fuse_args *args,
-	 const struct fuse_operations *op, size_t op_size,
-	 void *user_data)
-{
-	struct libfuse_version version = {
-		.major = FUSE_MAJOR_VERSION,
-		.minor = FUSE_MINOR_VERSION,
-		.hotfix = FUSE_HOTFIX_VERSION,
-		.padding = 0
-	};
-
-	return _fuse_new(args, op, op_size, &version, user_data);
-}
-#else /* LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS */
-struct fuse *_fuse_new_317(struct fuse_args *args,
-                      const struct fuse_operations *op, size_t op_size,
-		      struct libfuse_version *version,
-		      void *private_data);
-#define _fuse_new(args, op, size, version, data) \
-	_fuse_new_317(args, op, size, version, data)
-static inline struct fuse *
-fuse_new(struct fuse_args *args,
-	 const struct fuse_operations *op, size_t op_size,
-	 void *user_data)
-{
-	struct libfuse_version version = {
-		.major = FUSE_MAJOR_VERSION,
-		.minor = FUSE_MINOR_VERSION,
-		.hotfix = FUSE_HOTFIX_VERSION,
-		.padding = 0
-	};
-
-	return _fuse_new(args, op, op_size, &version, user_data);
-}
-#endif /* LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS */
+struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op,
+		      size_t op_size, void *private_data);
 #endif
 
 /**
@@ -1104,9 +990,6 @@
 #if FUSE_USE_VERSION < 32
 int fuse_loop_mt_31(struct fuse *f, int clone_fd);
 #define fuse_loop_mt(f, clone_fd) fuse_loop_mt_31(f, clone_fd)
-#elif FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
-#define fuse_loop_mt(f, config) fuse_loop_mt_32(f, config)
 #else
 /**
  * FUSE event loop with multiple threads
@@ -1134,19 +1017,14 @@
  * in the callback function of fuse_operations is also thread-safe.
  *
  * @param f the FUSE handle
- * @param config loop configuration, may be NULL and defaults will be used then
+ * @param config loop configuration
  * @return see fuse_session_loop()
  *
  * See also: fuse_loop()
  */
-#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
 int fuse_loop_mt(struct fuse *f, struct fuse_loop_config *config);
-#else
-#define fuse_loop_mt(f, config) fuse_loop_mt_312(f, config)
-#endif /* LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS */
 #endif
 
-
 /**
  * Get the current context
  *
@@ -1198,6 +1076,14 @@
 int fuse_invalidate_path(struct fuse *f, const char *path);
 
 /**
+ * The real main function
+ *
+ * Do not call this directly, use fuse_main()
+ */
+int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
+		   size_t op_size, void *private_data);
+
+/**
  * Start the cleanup thread when using option "remember".
  *
  * This is done automatically by fuse_loop_mt()
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 5e1e2f5..efaf754 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -14,17 +14,17 @@
 #ifndef FUSE_COMMON_H_
 #define FUSE_COMMON_H_
 
-#ifdef HAVE_LIBFUSE_PRIVATE_CONFIG_H
-#include "fuse_config.h"
-#endif
-
-#include "libfuse_config.h"
-
 #include "fuse_opt.h"
 #include "fuse_log.h"
 #include <stdint.h>
 #include <sys/types.h>
 
+/** Major version of FUSE library interface */
+#define FUSE_MAJOR_VERSION 3
+
+/** Minor version of FUSE library interface */
+#define FUSE_MINOR_VERSION 10
+
 #define FUSE_MAKE_VERSION(maj, min)  ((maj) * 100 + (min))
 #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
 
@@ -42,7 +42,7 @@
  * descriptors can share a single file handle.
  */
 struct fuse_file_info {
-	/** Open flags.	 Available in open(), release() and create() */
+	/** Open flags.	 Available in open() and release() */
 	int flags;
 
 	/** In case of a write operation indicates if this was caused
@@ -53,19 +53,16 @@
 	    requests if write caching had been disabled. */
 	unsigned int writepage : 1;
 
-	/** Can be filled in by open/create, to use direct I/O on this file. */
+	/** Can be filled in by open, to use direct I/O on this file. */
 	unsigned int direct_io : 1;
 
-	/** Can be filled in by open and opendir. It signals the kernel that any
-	    currently cached data (ie., data that the filesystem provided the
-	    last time the file/directory was open) need not be invalidated when
-	    the file/directory is closed. */
+	/** Can be filled in by open. It signals the kernel that any
+	    currently cached file data (ie., data that the filesystem
+	    provided the last time the file was open) need not be
+	    invalidated. Has no effect when set in other contexts (in
+	    particular it does nothing when set by opendir()). */
 	unsigned int keep_cache : 1;
 
-	/** Can be filled by open/create, to allow parallel direct writes on this
-         *  file */
-        unsigned int parallel_direct_writes : 1;
-
 	/** Indicates a flush operation.  Set in flush operation, also
 	    maybe set in highlevel lock operation and lowlevel release
 	    operation. */
@@ -86,12 +83,8 @@
 	    nothing when set by open()). */
 	unsigned int cache_readdir : 1;
 
-	/** Can be filled in by open, to indicate that flush is not needed
-	    on close. */
-	unsigned int noflush : 1;
-
 	/** Padding.  Reserved for future use*/
-	unsigned int padding : 23;
+	unsigned int padding : 25;
 	unsigned int padding2 : 32;
 
 	/** File handle id.  May be filled in by filesystem in create,
@@ -110,27 +103,13 @@
 	/** Requested poll events.  Available in ->poll.  Only set on kernels
 	    which support it.  If unsupported, this field is set to zero. */
 	uint32_t poll_events;
-
-	/** Passthrough backing file id.  May be filled in by filesystem in
-	 * create and open.  It is used to create a passthrough connection
-	 * between FUSE file and backing file. */
-	int32_t backing_id;
 };
 
-
-
 /**
  * Configuration parameters passed to fuse_session_loop_mt() and
  * fuse_loop_mt().
- * Deprecated and replaced by a newer private struct in FUSE API
- * version 312 (FUSE_MAKE_VERSION(3, 12)
  */
-#if FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
-struct fuse_loop_config_v1; /* forward declarition */
 struct fuse_loop_config {
-#else
-struct fuse_loop_config_v1 {
-#endif
 	/**
 	 * whether to use separate device fds for each thread
 	 * (may increase performance)
@@ -150,7 +129,6 @@
 	unsigned int max_idle_threads;
 };
 
-
 /**************************************************************************
  * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
  **************************************************************************/
@@ -187,11 +165,6 @@
 /**
  * Indicates that the filesystem supports lookups of "." and "..".
  *
- * When this flag is set, the filesystem must be prepared to receive requests
- * for invalid inodes (i.e., for which a FORGET request was received or
- * which have been used in a previous instance of the filesystem daemon) and
- * must not reuse node-ids (even when setting generation numbers).
- *
  * This feature is disabled by default.
  */
 #define FUSE_CAP_EXPORT_SUPPORT		(1 << 4)
@@ -335,10 +308,8 @@
  * kernel. (If this flag is not set, returning ENOSYS will be treated
  * as an error and signaled to the caller).
  *
- * Setting this flag in the `want` field enables this behavior automatically
- * within libfuse for low level API users. If non-low level users wish to have
- * this behavior you must return `ENOSYS` from the open() handler on supporting
- * kernels.
+ * Setting (or unsetting) this flag in the `want` field has *no
+ * effect*.
  */
 #define FUSE_CAP_NO_OPEN_SUPPORT	(1 << 17)
 
@@ -347,6 +318,8 @@
  * is unset, the FUSE kernel module will ensure that lookup() and
  * readdir() requests are never issued concurrently for the same
  * directory.
+ *
+ * This feature is enabled by default when supported by the kernel.
  */
 #define FUSE_CAP_PARALLEL_DIROPS        (1 << 18)
 
@@ -374,28 +347,11 @@
  * setuid and setgid bits when a file is written, truncated, or
  * its owner is changed.
  *
- * This feature is disabled by default.
+ * This feature is enabled by default when supported by the kernel.
  */
 #define FUSE_CAP_HANDLE_KILLPRIV         (1 << 20)
 
 /**
- * Indicates that the filesystem is responsible for unsetting
- * setuid and setgid bit and additionally cap (stored as xattr) when a
- * file is written, truncated, or its owner is changed.
- * Upon write/truncate suid/sgid is only killed if caller
- * does not have CAP_FSETID. Additionally upon
- * write/truncate sgid is killed only if file has group
- * execute permission. (Same as Linux VFS behavior).
- * KILLPRIV_V2 requires handling of
- *   - FUSE_OPEN_KILL_SUIDGID (set in struct fuse_create_in::open_flags)
- *   - FATTR_KILL_SUIDGID (set in struct fuse_setattr_in::valid)
- *   - FUSE_WRITE_KILL_SUIDGID (set in struct fuse_write_in::write_flags)
- *
- * This feature is disabled by default.
- */
-#define FUSE_CAP_HANDLE_KILLPRIV_V2         (1 << 21)
-
-/**
  * Indicates that the kernel supports caching symlinks in its page cache.
  *
  * When this feature is enabled, symlink targets are saved in the page cache.
@@ -416,10 +372,7 @@
  * flag is not set, returning ENOSYS will be treated as an error and signalled
  * to the caller.)
  *
- * Setting this flag in the `want` field enables this behavior automatically
- * within libfuse for low level API users.  If non-low level users with to have
- * this behavior you must return `ENOSYS` from the opendir() handler on
- * supporting kernels.
+ * Setting (or unsetting) this flag in the `want` field has *no effect*.
  */
 #define FUSE_CAP_NO_OPENDIR_SUPPORT    (1 << 24)
 
@@ -447,22 +400,6 @@
 #define FUSE_CAP_EXPLICIT_INVAL_DATA    (1 << 25)
 
 /**
- * Indicates support that dentries can be expired.
- * 
- * Expiring dentries, instead of invalidating them, makes a difference for 
- * overmounted dentries, where plain invalidation would detach all submounts 
- * before dropping the dentry from the cache. If only expiry is set on the 
- * dentry, then any overmounts are left alone and until ->d_revalidate() 
- * is called.
- * 
- * Note: ->d_revalidate() is not called for the case of following a submount,
- * so invalidation will only be triggered for the non-overmounted case. 
- * The dentry could also be mounted in a different mount instance, in which case
- * any submounts will still be detached.
-*/
-#define FUSE_CAP_EXPIRE_ONLY      (1 << 26)
-
-/**
  * Indicates that an extended 'struct fuse_setxattr' is used by the kernel
  * side - extra_flags are passed, which are used (as of now by acl) processing.
  * For example FUSE_SETXATTR_ACL_KILL_SGID might be set.
@@ -470,27 +407,6 @@
 #define FUSE_CAP_SETXATTR_EXT     (1 << 27)
 
 /**
- * Files opened with FUSE_DIRECT_IO do not support MAP_SHARED mmap. This restriction
- * is relaxed through FUSE_CAP_DIRECT_IO_RELAX (kernel flag: FUSE_DIRECT_IO_RELAX).
- * MAP_SHARED is disabled by default for FUSE_DIRECT_IO, as this flag can be used to
- * ensure coherency between mount points (or network clients) and with kernel page
- * cache as enforced by mmap that cannot be guaranteed anymore.
- */
-#define FUSE_CAP_DIRECT_IO_ALLOW_MMAP  (1 << 28)
-
-/**
- * Indicates support for passthrough mode access for read/write operations.
- *
- * If this flag is set in the `capable` field of the `fuse_conn_info`
- * structure, then the FUSE kernel module supports redirecting read/write
- * operations to the backing file instead of letting them to be handled
- * by the FUSE daemon.
- *
- * This feature is disabled by default.
- */
-#define FUSE_CAP_PASSTHROUGH_UPSTREAM      (1 << 29)
-
-/**
  * Indicates support for passthrough mode access for read/write operations.
  *
  * If this flag is set in the `capable` field of the `fuse_conn_info`
@@ -632,29 +548,9 @@
 	unsigned time_gran;
 
 	/**
-	 * When FUSE_CAP_PASSTHROUGH is enabled, this is the maximum allowed
-	 * stacking depth of the backing files.  In current kernel, the maximum
-	 * allowed stack depth if FILESYSTEM_MAX_STACK_DEPTH (2), which includes
-	 * the FUSE passthrough layer, so the maximum stacking depth for backing
-	 * files is 1.
-	 *
-	 * The default is FUSE_BACKING_STACKED_UNDER (0), meaning that the
-	 * backing files cannot be on a stacked filesystem, but another stacked
-	 * filesystem can be stacked over this FUSE passthrough filesystem.
-	 *
-	 * Set this to FUSE_BACKING_STACKED_OVER (1) if backing files may be on
-	 * a stacked filesystem, such as overlayfs or another FUSE passthrough.
-	 * In this configuration, another stacked filesystem cannot be stacked
-	 * over this FUSE passthrough filesystem.
-	 */
-#define FUSE_BACKING_STACKED_UNDER	(0)
-#define FUSE_BACKING_STACKED_OVER	(1)
-	unsigned max_backing_stack_depth;
-
-	/**
 	 * For future use.
 	 */
-	unsigned reserved[21];
+	unsigned reserved[22];
 };
 
 struct fuse_session;
@@ -890,18 +786,6 @@
 	struct fuse_buf buf[1];
 };
 
-/**
- * libfuse version a file system was compiled with. Should be filled in from
- * defines in 'libfuse_config.h'
- */
-struct libfuse_version
-{
-	int major;
-	int minor;
-	int hotfix;
-	int padding;
-};
-
 /* Initialize bufvec with a single buffer of given size */
 #define FUSE_BUFVEC_INIT(size__)				\
 	((struct fuse_bufvec) {					\
@@ -970,45 +854,6 @@
  */
 void fuse_remove_signal_handlers(struct fuse_session *se);
 
-/**
- * Create and set default config for fuse_session_loop_mt and fuse_loop_mt.
- *
- * @return anonymous config struct
- */
-struct fuse_loop_config *fuse_loop_cfg_create(void);
-
-/**
- * Free the config data structure
- */
-void fuse_loop_cfg_destroy(struct fuse_loop_config *config);
-
-/**
- * fuse_loop_config setter to set the number of max idle threads.
- */
-void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config,
-				    unsigned int value);
-
-/**
- * fuse_loop_config setter to set the number of max threads.
- */
-void fuse_loop_cfg_set_max_threads(struct fuse_loop_config *config,
-				   unsigned int value);
-
-/**
- * fuse_loop_config setter to enable the clone_fd feature
- */
-void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config,
-				unsigned int value);
-
-/**
- * Convert old config to more recernt fuse_loop_config2
- *
- * @param config current config2 type
- * @param v1_conf older config1 type (below FUSE API 312)
- */
-void fuse_loop_cfg_convert(struct fuse_loop_config *config,
-			   struct fuse_loop_config_v1 *v1_conf);
-
 /* ----------------------------------------------------------- *
  * Compatibility stuff					       *
  * ----------------------------------------------------------- */
@@ -1028,7 +873,7 @@
  * On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
  */
 
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus
 _Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
 #else
 struct _fuse_off_t_must_be_64bit_dummy_struct \
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index 8da1043..a88d89d 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -194,27 +194,6 @@
  *  - add FUSE_SECURITY_CTX init flag
  *  - add security context to create, mkdir, symlink, and mknod requests
  *  - add FUSE_HAS_INODE_DAX, FUSE_ATTR_DAX
- *
- *  7.37
- *  - add FUSE_TMPFILE
- *
- *  7.38
- *  - add FUSE_EXPIRE_ONLY flag to fuse_notify_inval_entry
- *  - add FOPEN_PARALLEL_DIRECT_WRITES
- *  - add total_extlen to fuse_in_header
- *  - add FUSE_MAX_NR_SECCTX
- *  - add extension header
- *  - add FUSE_EXT_GROUPS
- *  - add FUSE_CREATE_SUPP_GROUP
- *  - add FUSE_HAS_EXPIRE_ONLY
- *
- *  7.39
- *  - add FUSE_DIRECT_IO_ALLOW_MMAP
- *  - add FUSE_STATX and related structures
- *
- *  7.40
- *  - add max_stack_depth to fuse_init_out, add FUSE_PASSTHROUGH init flag
- *  - add backing_id to fuse_open_out, add FOPEN_PASSTHROUGH open flag
  */
 
 #ifndef _LINUX_FUSE_H
@@ -250,7 +229,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 40
+#define FUSE_KERNEL_MINOR_VERSION 36
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -277,40 +256,6 @@
 	uint32_t	flags;
 };
 
-/*
- * The following structures are bit-for-bit compatible with the statx(2) ABI in
- * Linux.
- */
-struct fuse_sx_time {
-	int64_t		tv_sec;
-	uint32_t	tv_nsec;
-	int32_t		__reserved;
-};
-
-struct fuse_statx {
-	uint32_t	mask;
-	uint32_t	blksize;
-	uint64_t	attributes;
-	uint32_t	nlink;
-	uint32_t	uid;
-	uint32_t	gid;
-	uint16_t	mode;
-	uint16_t	__spare0[1];
-	uint64_t	ino;
-	uint64_t	size;
-	uint64_t	blocks;
-	uint64_t	attributes_mask;
-	struct fuse_sx_time	atime;
-	struct fuse_sx_time	btime;
-	struct fuse_sx_time	ctime;
-	struct fuse_sx_time	mtime;
-	uint32_t	rdev_major;
-	uint32_t	rdev_minor;
-	uint32_t	dev_major;
-	uint32_t	dev_minor;
-	uint64_t	__spare2[14];
-};
-
 struct fuse_kstatfs {
 	uint64_t	blocks;
 	uint64_t	bfree;
@@ -356,8 +301,6 @@
  * FOPEN_CACHE_DIR: allow caching this directory
  * FOPEN_STREAM: the file is stream-like (no file position at all)
  * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE)
- * FOPEN_PARALLEL_DIRECT_WRITES: Allow concurrent direct writes on the same inode
- * FOPEN_PASSTHROUGH: passthrough read/write operations for this open file
  */
 #define FOPEN_DIRECT_IO		(1 << 0)
 #define FOPEN_KEEP_CACHE	(1 << 1)
@@ -365,8 +308,6 @@
 #define FOPEN_CACHE_DIR		(1 << 3)
 #define FOPEN_STREAM		(1 << 4)
 #define FOPEN_NOFLUSH		(1 << 5)
-#define FOPEN_PARALLEL_DIRECT_WRITES	(1 << 6)
-#define FOPEN_PASSTHROUGH	(1 << 7)
 
 /**
  * INIT request/reply flags
@@ -412,10 +353,6 @@
  * FUSE_SECURITY_CTX:	add security context to create, mkdir, symlink, and
  *			mknod
  * FUSE_HAS_INODE_DAX:  use per inode DAX
- * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
- *			symlink and mknod (single group that matches parent)
- * FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
- * FUSE_DIRECT_IO_ALLOW_MMAP: allow shared mmap in FOPEN_DIRECT_IO mode.
  */
 #define FUSE_ASYNC_READ		(1 << 0)
 #define FUSE_POSIX_LOCKS	(1 << 1)
@@ -452,13 +389,6 @@
 /* bits 32..63 get shifted down 32 bits into the flags2 field */
 #define FUSE_SECURITY_CTX	(1ULL << 32)
 #define FUSE_HAS_INODE_DAX	(1ULL << 33)
-#define FUSE_CREATE_SUPP_GROUP	(1ULL << 34)
-#define FUSE_HAS_EXPIRE_ONLY	(1ULL << 35)
-#define FUSE_DIRECT_IO_ALLOW_MMAP (1ULL << 36)
-#define FUSE_PASSTHROUGH_UPSTREAM	(1ULL << 37)
-
-/* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */
-#define FUSE_DIRECT_IO_RELAX	FUSE_DIRECT_IO_ALLOW_MMAP
 
 /*
  * For FUSE < 7.36 FUSE_PASSTHROUGH has value (1 << 31).
@@ -570,23 +500,6 @@
  */
 #define FUSE_SETXATTR_ACL_KILL_SGID	(1 << 0)
 
-/**
- * notify_inval_entry flags
- * FUSE_EXPIRE_ONLY
- */
-#define FUSE_EXPIRE_ONLY		(1 << 0)
-
-/**
- * extension type
- * FUSE_MAX_NR_SECCTX: maximum value of &fuse_secctx_header.nr_secctx
- * FUSE_EXT_GROUPS: &fuse_supp_groups extension
- */
-enum fuse_ext_type {
-	/* Types 0..31 are reserved for fuse_secctx_header */
-	FUSE_MAX_NR_SECCTX	= 31,
-	FUSE_EXT_GROUPS		= 32,
-};
-
 enum fuse_opcode {
 	FUSE_LOOKUP		= 1,
 	FUSE_FORGET		= 2,  /* no reply */
@@ -636,8 +549,6 @@
 	FUSE_SETUPMAPPING	= 48,
 	FUSE_REMOVEMAPPING	= 49,
 	FUSE_SYNCFS		= 50,
-	FUSE_TMPFILE		= 51,
-	FUSE_STATX		= 52,
 
 	/* Android specific operations */
 	FUSE_CANONICAL_PATH     = 2016,
@@ -716,22 +627,6 @@
 	struct fuse_attr attr;
 };
 
-struct fuse_statx_in {
-	uint32_t	getattr_flags;
-	uint32_t	reserved;
-	uint64_t	fh;
-	uint32_t	sx_flags;
-	uint32_t	sx_mask;
-};
-
-struct fuse_statx_out {
-	uint64_t	attr_valid;	/* Cache timeout for the attributes */
-	uint32_t	attr_valid_nsec;
-	uint32_t	flags;
-	uint64_t	spare[2];
-	struct fuse_statx stat;
-};
-
 #define FUSE_COMPAT_MKNOD_IN_SIZE 8
 
 struct fuse_mknod_in {
@@ -794,10 +689,7 @@
 struct fuse_open_out {
 	uint64_t	fh;
 	uint32_t	open_flags;
-	union {
-		uint32_t	passthrough_fh;
-		int32_t		backing_id;
-	};
+	uint32_t	passthrough_fh;
 };
 
 struct fuse_release_in {
@@ -926,8 +818,7 @@
 	uint16_t	max_pages;
 	uint16_t	map_alignment;
 	uint32_t	flags2;
-	uint32_t	max_stack_depth;
-	uint32_t	unused[6];
+	uint32_t	unused[7];
 };
 
 #define CUSE_INIT_INFO_MAX 4096
@@ -1018,13 +909,7 @@
 	uint32_t	uid;
 	uint32_t	gid;
 	uint32_t	pid;
-	union {
-		uint32_t	error_in;
-		struct {
-			uint16_t	total_extlen; /* length of extensions in 8byte units */
-			uint16_t	padding;
-		};
-	};
+	uint32_t	error_in;
 };
 
 struct fuse_out_header {
@@ -1069,7 +954,7 @@
 struct fuse_notify_inval_entry_out {
 	uint64_t	parent;
 	uint32_t	namelen;
-	uint32_t	flags;
+	uint32_t	padding;
 };
 
 struct fuse_notify_delete_out {
@@ -1104,19 +989,9 @@
 	uint64_t	dummy4;
 };
 
-struct fuse_backing_map {
-	int32_t		fd;
-	uint32_t	flags;
-	uint64_t	padding;
-};
-
 /* Device ioctls: */
 #define FUSE_DEV_IOC_MAGIC		229
 #define FUSE_DEV_IOC_CLONE		_IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t)
-#define FUSE_DEV_IOC_BACKING_OPEN	_IOW(FUSE_DEV_IOC_MAGIC, 1, \
-					     struct fuse_backing_map)
-#define FUSE_DEV_IOC_BACKING_CLOSE	_IOW(FUSE_DEV_IOC_MAGIC, 2, uint32_t)
-/* Android Passthrough ioctls */
 #define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V0 _IOW(229, 1, struct fuse_passthrough_out_v0)
 #define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V1 _IOW(229, 127, struct fuse_passthrough_out_v0)
 #define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2 _IOW(229, 126, uint32_t)
@@ -1198,29 +1073,6 @@
 	uint32_t	nr_secctx;
 };
 
-/**
- * struct fuse_ext_header - extension header
- * @size: total size of this extension including this header
- * @type: type of extension
- *
- * This is made compatible with fuse_secctx_header by using type values >
- * FUSE_MAX_NR_SECCTX
- */
-struct fuse_ext_header {
-	uint32_t	size;
-	uint32_t	type;
-};
-
-/**
- * struct fuse_supp_groups - Supplementary group extension
- * @nr_groups: number of supplementary groups
- * @groups: flexible array of group IDs
- */
-struct fuse_supp_groups {
-	uint32_t	nr_groups;
-	uint32_t	groups[];
-};
-
 /** Export fuse_args only for bpf */
 #ifdef __KERNEL__
 struct fuse_mount;
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index b35960a..92370ea 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -131,28 +131,6 @@
 	uint64_t nlookup;
 };
 
-struct fuse_custom_io {
-	ssize_t (*writev)(int fd, struct iovec *iov, int count, void *userdata);
-	ssize_t (*read)(int fd, void *buf, size_t buf_len, void *userdata);
-	ssize_t (*splice_receive)(int fdin, off_t *offin, int fdout,
-					  off_t *offout, size_t len,
-				  	  unsigned int flags, void *userdata);
-	ssize_t (*splice_send)(int fdin, off_t *offin, int fdout,
-				     off_t *offout, size_t len,
-			           unsigned int flags, void *userdata);
-	int (*clone_fd)(int master_fd);
-};
-
-/**
- * Flags for fuse_lowlevel_notify_entry()
- * 0 = invalidate entry
- * FUSE_LL_EXPIRE_ONLY = expire entry
-*/
-enum fuse_notify_entry_flags {
-	FUSE_LL_INVALIDATE = 0,
-	FUSE_LL_EXPIRE_ONLY	= (1 << 0),
-};
-
 /* 'to_set' flags in setattr */
 #define FUSE_SET_ATTR_MODE	(1 << 0)
 #define FUSE_SET_ATTR_UID	(1 << 1)
@@ -162,15 +140,7 @@
 #define FUSE_SET_ATTR_MTIME	(1 << 5)
 #define FUSE_SET_ATTR_ATIME_NOW	(1 << 7)
 #define FUSE_SET_ATTR_MTIME_NOW	(1 << 8)
-#define FUSE_SET_ATTR_FORCE	(1 << 9)
 #define FUSE_SET_ATTR_CTIME	(1 << 10)
-#define FUSE_SET_ATTR_KILL_SUID	(1 << 11)
-#define FUSE_SET_ATTR_KILL_SGID	(1 << 12)
-#define FUSE_SET_ATTR_FILE	(1 << 13)
-#define FUSE_SET_ATTR_KILL_PRIV	(1 << 14)
-#define FUSE_SET_ATTR_OPEN	(1 << 15)
-#define FUSE_SET_ATTR_TIMES_SET	(1 << 16)
-#define FUSE_SET_ATTR_TOUCH	(1 << 17)
 
 /* ----------------------------------------------------------- *
  * structs from fuse_kernel.h                                  *
@@ -344,12 +314,6 @@
 	 * expected to reset the setuid and setgid bits if the file
 	 * size or owner is being changed.
 	 *
-	 * This method will not be called to update st_atime or st_ctime implicitly
-	 * (eg. after a read() request), and only be called to implicitly update st_mtime
-	 * if writeback caching is active. It is the filesystem's responsibility to update
-	 * these timestamps when needed, and (if desired) to implement mount options like
-	 * `noatime` or `relatime`.
-	 *
 	 * If the setattr was invoked from the ftruncate() system call
 	 * under Linux kernel versions 2.6.15 or later, the fi->fh will
 	 * contain the value set by the open method or will be undefined
@@ -573,13 +537,6 @@
 	 * future calls to open and release will also succeed without being
 	 * sent to the filesystem process.
 	 *
-	 * To get this behavior without providing an opendir handler, you may
-	 * set FUSE_CAP_NO_OPEN_SUPPORT in `fuse_conn_info.want` on supported
-	 * kernels to automatically get the zero message open().
-	 *
-	 * If this callback is not provided and FUSE_CAP_NO_OPEN_SUPPORT is not
-	 * set in `fuse_conn_info.want` then an empty reply will be sent.
-	 *
 	 * Valid replies:
 	 *   fuse_reply_open
 	 *   fuse_reply_err
@@ -753,13 +710,6 @@
 	 * process. In addition, the kernel will cache readdir results
 	 * as if opendir returned FOPEN_KEEP_CACHE | FOPEN_CACHE_DIR.
 	 *
-	 * To get this behavior without providing an opendir handler, you may
-	 * set FUSE_CAP_NO_OPENDIR_SUPPORT in `fuse_conn_info.want` on supported
-	 * kernels to automatically get the zero message opendir().
-	 *
-	 * If this callback is not provided and FUSE_CAP_NO_OPENDIR_SUPPORT is
-	 * not set in `fuse_conn_info.want` then an empty reply will be sent.
-	 *
 	 * Valid replies:
 	 *   fuse_reply_open
 	 *   fuse_reply_err
@@ -1143,24 +1093,21 @@
 	/**
 	 * Poll for IO readiness
 	 *
-	 * The client should immediately respond with fuse_reply_poll(),
-	 * setting revents appropriately according to which events are ready.
-	 *
-	 * Additionally, if ph is non-NULL, the client must retain it and
-	 * notify when all future IO readiness events occur by calling
+	 * Note: If ph is non-NULL, the client should notify
+	 * when IO readiness events occur by calling
 	 * fuse_lowlevel_notify_poll() with the specified ph.
 	 *
-	 * Regardless of the number of times poll with a non-NULL ph is
-	 * received, a single notify_poll is enough to service all. (Notifying
-	 * more times incurs overhead but doesn't harm correctness.) Any
-	 * additional received handles can be immediately destroyed.
+	 * Regardless of the number of times poll with a non-NULL ph
+	 * is received, single notification is enough to clear all.
+	 * Notifying more times incurs overhead but doesn't harm
+	 * correctness.
 	 *
 	 * The callee is responsible for destroying ph with
 	 * fuse_pollhandle_destroy() when no longer in use.
 	 *
 	 * If this request is answered with an error code of ENOSYS, this is
 	 * treated as success (with a kernel-defined default poll-mask) and
-	 * future calls to poll() will succeed the same way without being send
+	 * future calls to pull() will succeed the same way without being send
 	 * to the filesystem process.
 	 *
 	 * Valid replies:
@@ -1473,19 +1420,6 @@
 int fuse_reply_canonical_path(fuse_req_t req, const char *path);
 
 /**
- * Setup passthrough backing file for open reply
- *
- * Possible requests:
- *   open, opendir, create
- *
- * @param req request handle
- * @param fd backing file descriptor
- * @return positive backing id for success, 0 for failure
- */
-int fuse_passthrough_open(fuse_req_t req, int fd);
-int fuse_passthrough_close(fuse_req_t req, int backing_id);
-
-/**
  * Reply with open parameters
  *
  * currently the following members of 'fi' are used:
@@ -1790,10 +1724,11 @@
 				     off_t off, off_t len);
 
 /**
- * Notify to invalidate parent attributes and the dentry matching parent/name
+ * Notify to invalidate parent attributes and the dentry matching
+ * parent/name
  *
  * To avoid a deadlock this function must not be called in the
- * execution path of a related filesystem operation or within any code
+ * execution path of a related filesytem operation or within any code
  * that could hold a lock that could be needed to execute such an
  * operation. As of kernel 4.18, a "related operation" is a lookup(),
  * symlink(), mknod(), mkdir(), unlink(), rename(), link() or create()
@@ -1817,37 +1752,6 @@
 				     const char *name, size_t namelen);
 
 /**
- * Notify to expire parent attributes and the dentry matching parent/name
- * 
- * Same restrictions apply as for fuse_lowlevel_notify_inval_entry()
- * 
- * Compared to invalidating an entry, expiring the entry results not in a
- * forceful removal of that entry from kernel cache but instead the next access
- * to it forces a lookup from the filesystem.
- * 
- * This makes a difference for overmounted dentries, where plain invalidation
- * would detach all submounts before dropping the dentry from the cache. 
- * If only expiry is set on the dentry, then any overmounts are left alone and
- * until ->d_revalidate() is called.
- * 
- * Note: ->d_revalidate() is not called for the case of following a submount,
- * so invalidation will only be triggered for the non-overmounted case.
- * The dentry could also be mounted in a different mount instance, in which case
- * any submounts will still be detached.
- * 
- * Added in FUSE protocol version 7.38. If the kernel does not support
- * this (or a newer) version, the function will return -ENOSYS and do nothing.
- *
- * @param se the session object
- * @param parent inode number
- * @param name file name
- * @param namelen strlen() of file name
- * @return zero for success, -errno for failure, -enosys if no kernel support
-*/
-int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent,
-                                      const char *name, size_t namelen);
-
-/**
  * This function behaves like fuse_lowlevel_notify_inval_entry() with
  * the following additional effect (at least as of Linux kernel 4.8):
  *
@@ -1857,7 +1761,7 @@
  * that the dentry has been deleted.
  *
  * To avoid a deadlock this function must not be called while
- * executing a related filesystem operation or while holding a lock
+ * executing a related filesytem operation or while holding a lock
  * that could be needed to execute such an operation (see the
  * description of fuse_lowlevel_notify_inval_entry() for more
  * details).
@@ -2040,11 +1944,6 @@
  * Filesystem setup & teardown                                 *
  * ----------------------------------------------------------- */
 
-/**
- * Note: Any addition to this struct needs to create a compatibility symbol
- *       for fuse_parse_cmdline(). For ABI compatibility reasons it is also
- *       not possible to remove struct members.
- */
 struct fuse_cmdline_opts {
 	int singlethread;
 	int foreground;
@@ -2054,11 +1953,7 @@
 	int show_version;
 	int show_help;
 	int clone_fd;
-	unsigned int max_idle_threads; /* discouraged, due to thread
-	                                * destruct overhead */
-
-	/* Added in libfuse-3.12 */
-	unsigned int max_threads;
+	unsigned int max_idle_threads;
 };
 
 /**
@@ -2079,50 +1974,8 @@
  * @param opts output argument for parsed options
  * @return 0 on success, -1 on failure
  */
-#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
 int fuse_parse_cmdline(struct fuse_args *args,
 		       struct fuse_cmdline_opts *opts);
-#else
-#if FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
-int fuse_parse_cmdline_30(struct fuse_args *args,
-			   struct fuse_cmdline_opts *opts);
-#define fuse_parse_cmdline(args, opts) fuse_parse_cmdline_30(args, opts)
-#else
-int fuse_parse_cmdline_312(struct fuse_args *args,
-			   struct fuse_cmdline_opts *opts);
-#define fuse_parse_cmdline(args, opts) fuse_parse_cmdline_312(args, opts)
-#endif
-#endif
-
-/*
- * This should mostly not be called directly, but instead the fuse_session_new()
- * macro should be used, which fills in the libfuse version compilation
- * is done against automatically.
- */
-struct fuse_session *_fuse_session_new_317(struct fuse_args *args,
-					  const struct fuse_lowlevel_ops *op,
-					  size_t op_size,
-					  struct libfuse_version *version,
-					  void *userdata);
-
-/* Do not call this directly, but only through fuse_session_new() */
-#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
-struct fuse_session *
-_fuse_session_new(struct fuse_args *args,
-		 const struct fuse_lowlevel_ops *op,
-		 size_t op_size,
-		 struct libfuse_version *version,
-		 void *userdata);
-#else
-struct fuse_session *
-_fuse_session_new_317(struct fuse_args *args,
-		      const struct fuse_lowlevel_ops *op,
-		      size_t op_size,
-		      struct libfuse_version *version,
-		      void *userdata);
-#define _fuse_session_new(args, op, op_size, version, userdata)	\
-	_fuse_session_new_317(args, op, op_size, version, userdata)
-#endif
 
 /**
  * Create a low level session.
@@ -2148,55 +2001,13 @@
  * @param args argument vector
  * @param op the (low-level) filesystem operations
  * @param op_size sizeof(struct fuse_lowlevel_ops)
- * @param version the libfuse version a file system server was compiled against
  * @param userdata user data
+ *
  * @return the fuse session on success, NULL on failure
  **/
-static inline struct fuse_session *
-fuse_session_new(struct fuse_args *args,
-		 const struct fuse_lowlevel_ops *op,
-		 size_t op_size,
-		 void *userdata)
-{
-	struct libfuse_version version = {
-		.major = FUSE_MAJOR_VERSION,
-		.minor = FUSE_MINOR_VERSION,
-		.hotfix = FUSE_HOTFIX_VERSION,
-		.padding = 0
-	};
-
-	return _fuse_session_new(args, op, op_size, &version, userdata);
-}
-
-/**
- * Set a file descriptor for the session.
- *
- * This function can be used if you want to have a custom communication
- * interface instead of using a mountpoint. In practice, this means that instead
- * of calling fuse_session_mount() and fuse_session_unmount(), one could call
- * fuse_session_custom_io() where fuse_session_mount() would have otherwise been
- * called.
- *
- * In `io`, implementations for read and writev MUST be provided. Otherwise -1
- * will be returned and `fd` will not be used. Implementations for `splice_send`
- * and `splice_receive` are optional. If they are not provided splice will not
- * be used for send or receive respectively.
- *
- * The provided file descriptor `fd` will be closed when fuse_session_destroy()
- * is called.
- *
- * @param se session object
- * @param io Custom io to use when retrieving/sending requests/responses
- * @param fd file descriptor for the session
- *
- * @return 0  on success
- * @return -EINVAL if `io`, `io->read` or `ìo->writev` are NULL
- * @return -EBADF  if `fd` was smaller than 0
- * @return -errno  if failed to allocate memory to store `io`
- *
- **/
-int fuse_session_custom_io(struct fuse_session *se,
-				   const struct fuse_custom_io *io, int fd);
+struct fuse_session *fuse_session_new(struct fuse_args *args,
+				      const struct fuse_lowlevel_ops *op,
+				      size_t op_size, void *userdata);
 
 /**
  * Mount a FUSE file system.
@@ -2233,40 +2044,34 @@
 int fuse_session_loop(struct fuse_session *se);
 
 #if FUSE_USE_VERSION < 32
-	int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
-	#define fuse_session_loop_mt(se, clone_fd) fuse_session_loop_mt_31(se, clone_fd)
-#elif FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
-	int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
-	#define fuse_session_loop_mt(se, config) fuse_session_loop_mt_32(se, config)
+int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
+#define fuse_session_loop_mt(se, clone_fd) fuse_session_loop_mt_31(se, clone_fd)
 #else
-	#if (defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
-		/**
-		 * Enter a multi-threaded event loop.
-		 *
-		 * For a description of the return value and the conditions when the
-		 * event loop exits, refer to the documentation of
-		 * fuse_session_loop().
-		 *
-		 * @param se the session
-		 * @param config session loop configuration
-		 * @return see fuse_session_loop()
-		 */
-		int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
-	#else
-		int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
-		#define fuse_session_loop_mt(se, config) fuse_session_loop_mt_312(se, config)
-	#endif
+#if (!defined(__UCLIBC__) && !defined(__APPLE__))
+/**
+ * Enter a multi-threaded event loop.
+ *
+ * For a description of the return value and the conditions when the
+ * event loop exits, refer to the documentation of
+ * fuse_session_loop().
+ *
+ * @param se the session
+ * @param config session loop configuration 
+ * @return see fuse_session_loop()
+ */
+int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
+#else
+int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
+#define fuse_session_loop_mt(se, config) fuse_session_loop_mt_32(se, config)
+#endif
 #endif
 
 /**
  * Flag a session as terminated.
  *
- * This will cause any running event loops to terminate on the next opportunity. If this function is
- * called by a thread that is not a FUSE worker thread, the next
- * opportunity will be when FUSE a request is received (which may be far in the future if the
- * filesystem is not currently being used by any clients). One way to avoid this delay is to
- * afterwards sent a signal to the main thread (if fuse_set_signal_handlers() is used, SIGPIPE
- * will cause the main thread to wake-up but otherwise be ignored).
+ * This function is invoked by the POSIX signal handlers, when
+ * registered using fuse_set_signal_handlers(). It will cause any
+ * running event loops to terminate on the next opportunity.
  *
  * @param se the session
  */
diff --git a/include/fuse_mount_compat.h b/include/fuse_mount_compat.h
deleted file mode 100644
index 0142b51..0000000
--- a/include/fuse_mount_compat.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-  FUSE: Filesystem in Userspace
-  Copyright (C) 2023 Giulio Benetti <giulio.benetti@benettiengineering.com>
-
-  Logging API.
-
-  This program can be distributed under the terms of the GNU LGPLv2.
-  See the file LICENSE
-*/
-
-#ifndef FUSE_MOUNT_COMPAT_H_
-#define FUSE_MOUNT_COMPAT_H_
-
-#include <sys/mount.h>
-
-/* Some libc don't define MS_*, so define them manually
- * (values taken from https://elixir.bootlin.com/linux/v4.0.9/source/include/uapi/linux/fs.h#L68 on)
- */
-#ifndef MS_DIRSYNC
-#define MS_DIRSYNC	128
-#endif
-#ifndef MS_REC
-#define MS_REC		16384
-#endif
-#ifndef MS_PRIVATE
-#define MS_PRIVATE	(1<<18)
-#endif
-#ifndef MS_LAZYTIME
-#define MS_LAZYTIME	(1<<25)
-#endif
-
-#ifndef UMOUNT_DETACH
-#define UMOUNT_DETACH	0x00000002	/* Just detach from the tree */
-#endif
-#ifndef UMOUNT_NOFOLLOW
-#define UMOUNT_NOFOLLOW	0x00000008	/* Don't follow symlink on umount */
-#endif
-#ifndef UMOUNT_UNUSED
-#define UMOUNT_UNUSED	0x80000000	/* Flag guaranteed to be unused */
-#endif
-
-#endif /* FUSE_MOUNT_COMPAT_H_ */
diff --git a/lib/buffer.c b/lib/buffer.c
index 4f2f491..757807a 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -11,7 +11,7 @@
 
 #define _GNU_SOURCE
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_lowlevel.h"
 #include <string.h>
diff --git a/lib/compat.c b/lib/compat.c
deleted file mode 100644
index 0bac39e..0000000
--- a/lib/compat.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
-
-  Helper functions to create (simple) standalone programs. With the
-  aid of these functions it should be possible to create full FUSE
-  file system by implementing nothing but the request handlers.
-
-  This program can be distributed under the terms of the GNU LGPLv2.
-  See the file COPYING.LIB.
-*/
-
-/* Description:
-    This file has compatibility symbols for platforms that do not
-    support version symboling
-*/
-
-#include "fuse_config.h"
-#include "fuse_i.h"
-#include "fuse_misc.h"
-#include "fuse_opt.h"
-#include "fuse_lowlevel.h"
-#include "mount_util.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <string.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/param.h>
-
-/**
- * Compatibility ABI symbol for systems that do not support version symboling
- */
-#if (!defined(LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS))
-/* With current libfuse fuse_parse_cmdline is a macro pointing to the
- * versioned function. Here in this file we need to provide the ABI symbol
- * and the redirecting macro is conflicting.
- */
-#ifdef fuse_parse_cmdline
-#undef fuse_parse_cmdline
-#endif
-int fuse_parse_cmdline_30(struct fuse_args *args,
-                           struct fuse_cmdline_opts *opts);
-int fuse_parse_cmdline(struct fuse_args *args,
-		       struct fuse_cmdline_opts *opts);
-int fuse_parse_cmdline(struct fuse_args *args,
-		       struct fuse_cmdline_opts *opts)
-{
-	return fuse_parse_cmdline_30(args, opts);
-}
-#endif
-
-
diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c
index cd68787..b70947e 100644
--- a/lib/cuse_lowlevel.c
+++ b/lib/cuse_lowlevel.c
@@ -7,7 +7,7 @@
   See the file COPYING.LIB.
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "cuse_lowlevel.h"
 #include "fuse_kernel.h"
 #include "fuse_i.h"
@@ -351,9 +351,10 @@
 		return 1;
 
 	if (multithreaded) {
-		struct fuse_loop_config *config = fuse_loop_cfg_create();
-		res = fuse_session_loop_mt(se, config);
-		fuse_loop_cfg_destroy(config);
+		struct fuse_loop_config config;
+		config.clone_fd = 0;
+		config.max_idle_threads = 10;
+		res = fuse_session_loop_mt_32(se, &config);
 	}
 	else
 		res = fuse_session_loop(se);
diff --git a/lib/fuse.c b/lib/fuse.c
index 8617168..a95d7c1 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -9,7 +9,11 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_config.h"
+
+/* For pthread_rwlock_t */
+#define _GNU_SOURCE
+
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_lowlevel.h"
 #include "fuse_opt.h"
@@ -55,6 +59,7 @@
 
 struct fuse_fs {
 	struct fuse_operations op;
+	struct fuse_module *m;
 	void *user_data;
 	int debug;
 };
@@ -76,6 +81,8 @@
 	char **path2;
 	struct node **wnode2;
 	int err;
+	bool first_locked : 1;
+	bool second_locked : 1;
 	bool done : 1;
 };
 
@@ -245,7 +252,7 @@
 	int ret = -1;
 	char *tmp;
 	struct fusemod_so *so;
-	fuse_module_factory_t *factory;
+	fuse_module_factory_t factory;
 
 	tmp = malloc(strlen(module) + 64);
 	if (!tmp) {
@@ -267,13 +274,13 @@
 	}
 
 	sprintf(tmp, "fuse_module_%s_factory", module);
-	factory = (fuse_module_factory_t*)dlsym(so->handle, tmp);
+	*(void**)(&factory) = dlsym(so->handle, tmp);
 	if (factory == NULL) {
 		fuse_log(FUSE_LOG_ERR, "fuse: symbol <%s> not found in module: %s\n",
 			tmp, dlerror());
 		goto out_dlclose;
 	}
-	ret = fuse_register_module(module, *factory, so);
+	ret = fuse_register_module(module, factory, so);
 	if (ret)
 		goto out_dlclose;
 
@@ -1030,7 +1037,7 @@
 
 	for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID;
 	     node = node->parent) {
-		err = -ESTALE;
+		err = -ENOENT;
 		if (node->name == NULL || node->parent == NULL)
 			goto out_unlock;
 
@@ -1069,30 +1076,26 @@
 	return err;
 }
 
-static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
-			 fuse_ino_t nodeid2, const char *name2,
-			 char **path1, char **path2,
-			 struct node **wnode1, struct node **wnode2)
+static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe)
 {
-	int err;
+	struct node *wnode;
 
-	/* FIXME: locking two paths needs deadlock checking */
-	err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
-	if (!err) {
-		err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
-		if (err) {
-			struct node *wn1 = wnode1 ? *wnode1 : NULL;
-
-			unlock_path(f, nodeid1, wn1, NULL);
-			free(*path1);
-		}
+	if (qe->first_locked) {
+		wnode = qe->wnode1 ? *qe->wnode1 : NULL;
+		unlock_path(f, qe->nodeid1, wnode, NULL);
+		qe->first_locked = false;
 	}
-	return err;
+	if (qe->second_locked) {
+		wnode = qe->wnode2 ? *qe->wnode2 : NULL;
+		unlock_path(f, qe->nodeid2, wnode, NULL);
+		qe->second_locked = false;
+	}
 }
 
 static void queue_element_wakeup(struct fuse *f, struct lock_queue_element *qe)
 {
 	int err;
+	bool first = (qe == f->lockq);
 
 	if (!qe->path1) {
 		/* Just waiting for it to be unlocked */
@@ -1102,21 +1105,44 @@
 		return;
 	}
 
-	if (qe->done)
-		return;  // Don't try to double-lock the element
-
-	if (!qe->path2) {
+	if (!qe->first_locked) {
 		err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
 				   qe->wnode1, true);
-	} else {
-		err = try_get_path2(f, qe->nodeid1, qe->name1, qe->nodeid2,
-				    qe->name2, qe->path1, qe->path2, qe->wnode1,
-				    qe->wnode2);
+		if (!err)
+			qe->first_locked = true;
+		else if (err != -EAGAIN)
+			goto err_unlock;
+	}
+	if (!qe->second_locked && qe->path2) {
+		err = try_get_path(f, qe->nodeid2, qe->name2, qe->path2,
+				   qe->wnode2, true);
+		if (!err)
+			qe->second_locked = true;
+		else if (err != -EAGAIN)
+			goto err_unlock;
 	}
 
-	if (err == -EAGAIN)
-		return;  /* keep trying */
+	if (qe->first_locked && (qe->second_locked || !qe->path2)) {
+		err = 0;
+		goto done;
+	}
 
+	/*
+	 * Only let the first element be partially locked otherwise there could
+	 * be a deadlock.
+	 *
+	 * But do allow the first element to be partially locked to prevent
+	 * starvation.
+	 */
+	if (!first)
+		queue_element_unlock(f, qe);
+
+	/* keep trying */
+	return;
+
+err_unlock:
+	queue_element_unlock(f, qe);
+done:
 	qe->err = err;
 	qe->done = true;
 	pthread_cond_signal(&qe->cond);
@@ -1154,6 +1180,8 @@
 	struct lock_queue_element **qp;
 
 	qe->done = false;
+	qe->first_locked = false;
+	qe->second_locked = false;
 	pthread_cond_init(&qe->cond, NULL);
 	qe->next = NULL;
 	for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
@@ -1218,7 +1246,7 @@
 		*path = NULL;
 	} else {
 		err = get_path_common(f, nodeid, NULL, path, NULL);
-		if (err == -ESTALE)
+		if (err == -ENOENT)
 			err = 0;
 	}
 
@@ -1280,6 +1308,27 @@
 }
 #endif
 
+static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
+			 fuse_ino_t nodeid2, const char *name2,
+			 char **path1, char **path2,
+			 struct node **wnode1, struct node **wnode2)
+{
+	int err;
+
+	/* FIXME: locking two paths needs deadlock checking */
+	err = try_get_path(f, nodeid1, name1, path1, wnode1, true);
+	if (!err) {
+		err = try_get_path(f, nodeid2, name2, path2, wnode2, true);
+		if (err) {
+			struct node *wn1 = wnode1 ? *wnode1 : NULL;
+
+			unlock_path(f, nodeid1, wn1, NULL);
+			free(*path1);
+		}
+	}
+	return err;
+}
+
 static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1,
 		     fuse_ino_t nodeid2, const char *name2,
 		     char **path1, char **path2,
@@ -2619,6 +2668,9 @@
 	fuse_get_context()->private_data = fs->user_data;
 	if (fs->op.destroy)
 		fs->op.destroy(fs->user_data);
+	if (fs->m)
+		fuse_put_module(fs->m);
+	free(fs);
 }
 
 static void fuse_lib_destroy(void *data)
@@ -2627,6 +2679,7 @@
 
 	fuse_create_context(f);
 	fuse_fs_destroy(f->fs);
+	f->fs = NULL;
 }
 
 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
@@ -2963,20 +3016,6 @@
 		fuse_prepare_interrupt(f, req, &d);
 		if (!f->conf.hard_remove && is_open(f, parent, name)) {
 			err = hide_node(f, path, parent, name);
-			if (!err) {
-				/* we have hidden the node so now check again under a lock in case it is not used any more */
-				if (!is_open(f, parent, wnode->name)) {
-					char *unlinkpath;
-
-					/* get the hidden file path, to unlink it */
-					if (try_get_path(f, wnode->nodeid, NULL, &unlinkpath, NULL, false) == 0) {
-						err = fuse_fs_unlink(f->fs, unlinkpath);
-						if (!err)
-							remove_node(f, parent, wnode->name);
-						free(unlinkpath);
-					}
-				}
-			}
 		} else {
 			err = fuse_fs_unlink(f->fs, path);
 			if (!err)
@@ -3153,9 +3192,7 @@
 					fi->direct_io = 1;
 				if (f->conf.kernel_cache)
 					fi->keep_cache = 1;
-				if (fi->direct_io &&
-				    f->conf.parallel_direct_writes)
-					fi->parallel_direct_writes = 1;
+
 			}
 		}
 		fuse_finish_interrupt(f, req, &d);
@@ -3235,14 +3272,6 @@
 
 			if (f->conf.auto_cache)
 				open_auto_cache(f, ino, path, fi);
-
-			if (f->conf.no_rofd_flush &&
-			    (fi->flags & O_ACCMODE) == O_RDONLY)
-				fi->noflush = 1;
-
-			if (fi->direct_io && f->conf.parallel_direct_writes)
-				fi->parallel_direct_writes = 1;
-
 		}
 		fuse_finish_interrupt(f, req, &d);
 	}
@@ -3374,8 +3403,6 @@
 		err = fuse_fs_opendir(f->fs, path, &fi);
 		fuse_finish_interrupt(f, req, &d);
 		dh->fh = fi.fh;
-		llfi->cache_readdir = fi.cache_readdir;
-		llfi->keep_cache = fi.keep_cache;
 	}
 	if (!err) {
 		if (fuse_reply_open(req, llfi) == -ENOENT) {
@@ -3541,6 +3568,14 @@
 
 	if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
 		e.attr = *statp;
+
+		if (!is_dot_or_dotdot(name)) {
+			res = do_lookup(f, dh->nodeid, name, &e);
+			if (res) {
+				dh->error = res;
+				return 1;
+			}
+		}
 	} else {
 		e.attr.st_ino = FUSE_UNKNOWN_INO;
 		if (statp) {
@@ -3569,16 +3604,6 @@
 		if (extend_contents(dh, dh->needlen) == -1)
 			return 1;
 
-		if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
-			if (!is_dot_or_dotdot(name)) {
-				res = do_lookup(f, dh->nodeid, name, &e);
-				if (res) {
-					dh->error = res;
-					return 1;
-				}
-			}
-		}
-
 		newlen = dh->len +
 			fuse_add_direntry_plus(dh->req, dh->contents + dh->len,
 					       dh->needlen - dh->len, name,
@@ -3651,7 +3676,6 @@
 {
 	off_t pos;
 	struct fuse_direntry *de = dh->first;
-	int res;
 
 	dh->len = 0;
 
@@ -3676,16 +3700,6 @@
 				.ino = 0,
 				.attr = de->stat,
 			};
-
-			if (!is_dot_or_dotdot(de->name)) {
-				res = do_lookup(dh->fuse, dh->nodeid,
-						de->name, &e);
-				if (res) {
-					dh->error = res;
-					return 1;
-				}
-			}
-
 			thislen = fuse_add_direntry_plus(req, p, rem,
 							 de->name, &e, pos);
 		} else {
@@ -4275,8 +4289,6 @@
 	fuse_finish_interrupt(f, req, &d);
 	free_path(f, ino, path);
 
-	if (err < 0)
-		goto err;
 	fuse_reply_ioctl(req, err, out_buf, out_bufsz);
 	goto out;
 err:
@@ -4562,8 +4574,8 @@
 	return fuse_session_loop(f->se);
 }
 
-FUSE_SYMVER("fuse_loop_mt_312", "fuse_loop_mt@@FUSE_3.12")
-int fuse_loop_mt_312(struct fuse *f, struct fuse_loop_config *config)
+FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@@FUSE_3.2")
+int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
 {
 	if (f == NULL)
 		return -1;
@@ -4572,45 +4584,19 @@
 	if (res)
 		return -1;
 
-	res = fuse_session_loop_mt_312(fuse_get_session(f), config);
+	res = fuse_session_loop_mt_32(fuse_get_session(f), config);
 	fuse_stop_cleanup_thread(f);
 	return res;
 }
 
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1);
-FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@FUSE_3.2")
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1)
-{
-	struct fuse_loop_config *config = fuse_loop_cfg_create();
-	if (config == NULL)
-		return ENOMEM;
-
-	fuse_loop_cfg_convert(config, config_v1);
-
-	int res = fuse_loop_mt_312(f, config);
-
-	fuse_loop_cfg_destroy(config);
-
-	return res;
-}
-
 int fuse_loop_mt_31(struct fuse *f, int clone_fd);
 FUSE_SYMVER("fuse_loop_mt_31", "fuse_loop_mt@FUSE_3.0")
 int fuse_loop_mt_31(struct fuse *f, int clone_fd)
 {
-	int err;
-	struct fuse_loop_config *config = fuse_loop_cfg_create();
-
-	if (config == NULL)
-		return ENOMEM;
-
-	fuse_loop_cfg_set_clone_fd(config, clone_fd);
-
-	err = fuse_loop_mt_312(f, config);
-
-	fuse_loop_cfg_destroy(config);
-
-	return err;
+	struct fuse_loop_config config;
+	config.clone_fd = clone_fd;
+	config.max_idle_threads = 10;
+	return fuse_loop_mt_32(f, &config);
 }
 
 void fuse_exit(struct fuse *f)
@@ -4667,7 +4653,6 @@
 	FUSE_LIB_OPT("kernel_cache",	      kernel_cache, 1),
 	FUSE_LIB_OPT("auto_cache",	      auto_cache, 1),
 	FUSE_LIB_OPT("noauto_cache",	      auto_cache, 0),
-	FUSE_LIB_OPT("no_rofd_flush",	      no_rofd_flush, 1),
 	FUSE_LIB_OPT("umask=",		      set_mode, 1),
 	FUSE_LIB_OPT("umask=%o",	      umask, 0),
 	FUSE_LIB_OPT("uid=",		      set_uid, 1),
@@ -4682,7 +4667,6 @@
 	FUSE_LIB_OPT("noforget",              remember, -1),
 	FUSE_LIB_OPT("remember=%u",           remember, 0),
 	FUSE_LIB_OPT("modules=%s",	      modules, 0),
-	FUSE_LIB_OPT("parallel_direct_write=%d", parallel_direct_writes, 0),
 	FUSE_OPT_END
 };
 
@@ -4721,7 +4705,6 @@
 	printf(
 "    -o kernel_cache        cache files in kernel\n"
 "    -o [no]auto_cache      enable caching based on modification times (off)\n"
-"    -o no_rofd_flush       disable flushing of read-only fd on close (off)\n"
 "    -o umask=M             set file permissions (octal)\n"
 "    -o uid=N               set file owner\n"
 "    -o gid=N               set file group\n"
@@ -4820,6 +4803,7 @@
 		fuse_put_module(m);
 		return -1;
 	}
+	newfs->m = m;
 	f->fs = newfs;
 	return 0;
 }
@@ -4890,19 +4874,11 @@
 	}
 }
 
-/*
- * Not supposed to be called directly, but supposed to be called
- * through the fuse_new macro
- */
-struct fuse *_fuse_new_317(struct fuse_args *args,
-			   const struct fuse_operations *op,
-			   size_t op_size, struct libfuse_version *version,
-			   void *user_data);
-FUSE_SYMVER("_fuse_new_317", "_fuse_new@@FUSE_3.17")
-struct fuse *_fuse_new_317(struct fuse_args *args,
-			   const struct fuse_operations *op,
-			   size_t op_size, struct libfuse_version *version,
-			   void *user_data)
+
+FUSE_SYMVER("fuse_new_31", "fuse_new@@FUSE_3.1")
+struct fuse *fuse_new_31(struct fuse_args *args,
+		      const struct fuse_operations *op,
+		      size_t op_size, void *user_data)
 {
 	struct fuse *f;
 	struct node *root;
@@ -4984,7 +4960,7 @@
 	f->conf.readdir_ino = 1;
 #endif
 
-	f->se = _fuse_session_new(args, &llop, sizeof(llop), version, f);
+	f->se = fuse_session_new(args, &llop, sizeof(llop), f);
 	if (f->se == NULL)
 		goto out_free_fs;
 
@@ -5038,6 +5014,8 @@
 out_free_session:
 	fuse_session_destroy(f->se);
 out_free_fs:
+	if (f->fs->m)
+		fuse_put_module(f->fs->m);
 	free(f->fs);
 	free(f->conf.modules);
 out_delete_context_key:
@@ -5049,62 +5027,16 @@
 }
 
 /* Emulates 3.0-style fuse_new(), which processes --help */
-struct fuse *_fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
-			 size_t op_size,
-			 struct libfuse_version *version,
-			 void *user_data);
-FUSE_SYMVER("_fuse_new_30", "_fuse_new@FUSE_3.0")
-struct fuse *_fuse_new_30(struct fuse_args *args,
-			 const struct fuse_operations *op,
-			 size_t op_size,
-			 struct libfuse_version *version,
-			 void *user_data)
-{
-	struct fuse_config conf = {0};
-
-	const struct fuse_opt opts[] = {
-		FUSE_LIB_OPT("-h", show_help, 1),
-		FUSE_LIB_OPT("--help", show_help, 1),
-		FUSE_OPT_END
-	};
-
-	if (fuse_opt_parse(args, &conf, opts,
-			   fuse_lib_opt_proc) == -1)
-		return NULL;
-
-	if (conf.show_help) {
-		fuse_lib_help(args);
-		return NULL;
-	} else
-		return _fuse_new_317(args, op, op_size, version, user_data);
-}
-
-/* ABI compat version */
-struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
-			 size_t op_size, void *user_data);
-FUSE_SYMVER("fuse_new_31", "fuse_new@FUSE_3.1")
-struct fuse *fuse_new_31(struct fuse_args *args,
-			 const struct fuse_operations *op,
-			 size_t op_size, void *user_data)
-{
-		/* unknown version */
-	struct libfuse_version version = { 0 };
-
-	return _fuse_new_317(args, op, op_size, &version, user_data);
-}
-
-/*
- * ABI compat version
- * Emulates 3.0-style fuse_new(), which processes --help
- */
 struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
-			 size_t op_size, void *user_data);
+			 size_t op_size, void *private_data);
 FUSE_SYMVER("fuse_new_30", "fuse_new@FUSE_3.0")
 struct fuse *fuse_new_30(struct fuse_args *args,
 			 const struct fuse_operations *op,
 			 size_t op_size, void *user_data)
 {
-	struct fuse_config conf = {0};
+	struct fuse_config conf;
+
+	memset(&conf, 0, sizeof(conf));
 
 	const struct fuse_opt opts[] = {
 		FUSE_LIB_OPT("-h", show_help, 1),
@@ -5123,7 +5055,6 @@
 		return fuse_new_31(args, op, op_size, user_data);
 }
 
-
 void fuse_destroy(struct fuse *f)
 {
 	size_t i;
@@ -5169,7 +5100,6 @@
 	free(f->name_table.array);
 	pthread_mutex_destroy(&f->lock);
 	fuse_session_destroy(f->se);
-	free(f->fs);
 	free(f->conf.modules);
 	free(f);
 	fuse_delete_context_key();
diff --git a/lib/fuse_config.h b/lib/fuse_config.h
deleted file mode 100644
index 96154c9..0000000
--- a/lib/fuse_config.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Autogenerated by the Meson build system.
- * Do not edit, your changes will be lost.
- */
-
-#pragma once
-
-#define HAVE_COPY_FILE_RANGE
-
-#define HAVE_FALLOCATE
-
-#define HAVE_FDATASYNC
-
-#define HAVE_FORK
-
-#define HAVE_FSTATAT
-
-#define HAVE_ICONV
-
-#define HAVE_OPENAT
-
-#define HAVE_PIPE2
-
-#define HAVE_POSIX_FALLOCATE
-
-#define HAVE_READLINKAT
-
-#define HAVE_SETXATTR
-
-#define HAVE_SPLICE
-
-#define HAVE_STRUCT_STAT_ST_ATIM
-
-#undef HAVE_STRUCT_STAT_ST_ATIMESPEC
-
-#define HAVE_UTIMENSAT
-
-#define HAVE_VMSPLICE
-
-#define PACKAGE_VERSION "3.16.2"
-
-#include "android_config.h"
-
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 7a2ae04..d38b630 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -45,7 +45,6 @@
 	char *mountpoint;
 	volatile int exited;
 	int fd;
-	struct fuse_custom_io *io;
 	struct mount_opts *mo;
 	int debug;
 	int deny_others;
@@ -65,11 +64,6 @@
 	struct fuse_notify_req notify_list;
 	size_t bufsize;
 	int error;
-
-	/* This is useful if any kind of ABI incompatibility is found at
-	 * a later version, to 'fix' it at run time.
-	 */
-	struct libfuse_version version;
 };
 
 struct fuse_chan {
@@ -93,57 +87,6 @@
 	int ctr;
 };
 
-/**
- * Configuration parameters passed to fuse_session_loop_mt() and
- * fuse_loop_mt().
- *
- * Internal API to avoid exposing the plain data structure and
- * causing compat issues after adding or removing struct members.
- *
- */
-#if FUSE_USE_VERSION >= FUSE_MAKE_VERSION(3, 12)
-struct fuse_loop_config
-{
-	/* verififier that a correct struct was was passed. This is especially
-	 * needed, as versions below (3, 12) were using a public struct
-	 * (now called  fuse_loop_config_v1), which was hard to extend with
-	 * additional parameters, without risking that file system implementations
-	 * would not have noticed and might either pass uninitialized members
-	 * or even too small structs.
-	 * fuse_loop_config_v1 has clone_fd at this offset, which should be either 0
-	 * or 1. v2 or even higher version just need to set a value here
-	 * which not conflicting and very unlikely as having been set by
-	 * file system implementation.
-	 */
-	int version_id;
-
-	/**
-	 * whether to use separate device fds for each thread
-	 * (may increase performance)
-	 */
-	int clone_fd;
-	/**
-	 * The maximum number of available worker threads before they
-	 * start to get deleted when they become idle. If not
-	 * specified, the default is 10.
-	 *
-	 * Adjusting this has performance implications; a very small number
-	 * of threads in the pool will cause a lot of thread creation and
-	 * deletion overhead and performance may suffer. When set to 0, a new
-	 * thread will be created to service every operation.
-	 * The special value of -1 means that this parameter is disabled.
-	 */
-	int max_idle_threads;
-
-	/**
-	 *  max number of threads taking and processing kernel requests
-	 *
-	 *  As of now threads are created dynamically
-	 */
-	unsigned int max_threads;
-};
-#endif
-
 /* ----------------------------------------------------------- *
  * Channel interface (when using -o clone_fd)		       *
  * ----------------------------------------------------------- */
@@ -185,16 +128,8 @@
 
 struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
 		      size_t op_size, void *private_data);
-int fuse_loop_mt_312(struct fuse *f, struct fuse_loop_config *config);
-int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
-
-/**
- * Internal verifier for the given config.
- *
- * @return negative standard error code or 0 on success
- */
-int fuse_loop_cfg_verify(struct fuse_loop_config *config);
-
+int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
+int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
 
 #define FUSE_MAX_MAX_PAGES 256
 #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c
index b9c498b..e6560aa 100644
--- a/lib/fuse_loop.c
+++ b/lib/fuse_loop.c
@@ -8,7 +8,7 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_lowlevel.h"
 #include "fuse_i.h"
 
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index ecf8af8..8fcc46c 100644
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -8,7 +8,7 @@
   See the file COPYING.LIB.
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_lowlevel.h"
 #include "fuse_misc.h"
 #include "fuse_kernel.h"
@@ -24,20 +24,10 @@
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <assert.h>
-#include <limits.h>
 
 /* Environment var controlling the thread stack size */
 #define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK"
 
-#define FUSE_LOOP_MT_V2_IDENTIFIER	 INT_MAX - 2
-#define FUSE_LOOP_MT_DEF_CLONE_FD	 0
-#define FUSE_LOOP_MT_DEF_MAX_THREADS 10
-#define FUSE_LOOP_MT_DEF_IDLE_THREADS -1 /* thread destruction is disabled
-                                          * by default */
-
-/* an arbitrary large value that cannot be valid */
-#define FUSE_LOOP_MT_MAX_THREADS      (100U * 1000)
-
 struct fuse_worker {
 	struct fuse_worker *prev;
 	struct fuse_worker *next;
@@ -61,7 +51,6 @@
 	int error;
 	int clone_fd;
 	int max_idle;
-	int max_threads;
 };
 
 static struct fuse_chan *fuse_chan_new(int fd)
@@ -166,7 +155,7 @@
 
 		if (!isforget)
 			mt->numavail--;
-		if (mt->numavail == 0 && mt->numworker < mt->max_threads)
+		if (mt->numavail == 0)
 			fuse_loop_start_thread(mt);
 		pthread_mutex_unlock(&mt->lock);
 
@@ -175,14 +164,7 @@
 		pthread_mutex_lock(&mt->lock);
 		if (!isforget)
 			mt->numavail++;
-
-		/* creating and destroying threads is rather expensive - and there is
-		 * not much gain from destroying existing threads. It is therefore
-		 * discouraged to set max_idle to anything else than -1. If there
-		 * is indeed a good reason to destruct threads it should be done
-		 * delayed, a moving average might be useful for that.
-		 */
-		if (mt->max_idle != -1 && mt->numavail > mt->max_idle && mt->numworker > 1) {
+		if (mt->numavail > mt->max_idle) {
 			if (mt->exit) {
 				pthread_mutex_unlock(&mt->lock);
 				return NULL;
@@ -214,10 +196,7 @@
 	pthread_attr_t attr;
 	char *stack_size;
 
-	/* Override default stack size
-	 * XXX: This should ideally be a parameter option. It is rather
-	 *      well hidden here.
-	 */
+	/* Override default stack size */
 	pthread_attr_init(&attr);
 	stack_size = getenv(ENVNAME_THREAD_STACK);
 	if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size)))
@@ -242,11 +221,12 @@
 	return 0;
 }
 
-static int fuse_clone_chan_fd_default(struct fuse_session *se)
+static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt)
 {
 	int res;
 	int clonefd;
 	uint32_t masterfd;
+	struct fuse_chan *newch;
 	const char *devname = "/dev/fuse";
 
 #ifndef O_CLOEXEC
@@ -256,40 +236,18 @@
 	if (clonefd == -1) {
 		fuse_log(FUSE_LOG_ERR, "fuse: failed to open %s: %s\n", devname,
 			strerror(errno));
-		return -1;
+		return NULL;
 	}
-#ifndef O_CLOEXEC
 	fcntl(clonefd, F_SETFD, FD_CLOEXEC);
-#endif
 
-	masterfd = se->fd;
+	masterfd = mt->se->fd;
 	res = ioctl(clonefd, FUSE_DEV_IOC_CLONE, &masterfd);
 	if (res == -1) {
 		fuse_log(FUSE_LOG_ERR, "fuse: failed to clone device fd: %s\n",
 			strerror(errno));
 		close(clonefd);
-		return -1;
-	}
-	return clonefd;
-}
-
-static struct fuse_chan *fuse_clone_chan(struct fuse_mt *mt)
-{
-	int clonefd;
-	struct fuse_session *se = mt->se;
-	struct fuse_chan *newch;
-
-	if (se->io != NULL) {
-		if (se->io->clone_fd != NULL)
-			clonefd = se->io->clone_fd(se->fd);
-		else
-			return NULL;
-	} else {
-		clonefd = fuse_clone_chan_fd_default(se);
-	}
-	if (clonefd < 0)
 		return NULL;
-
+	}
 	newch = fuse_chan_new(clonefd);
 	if (newch == NULL)
 		close(clonefd);
@@ -345,25 +303,12 @@
 	free(w);
 }
 
-int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
-FUSE_SYMVER("fuse_session_loop_mt_312", "fuse_session_loop_mt@@FUSE_3.12")
-int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config)
+FUSE_SYMVER("fuse_session_loop_mt_32", "fuse_session_loop_mt@@FUSE_3.2")
+int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config)
 {
-int err;
+	int err;
 	struct fuse_mt mt;
 	struct fuse_worker *w;
-	int created_config = 0;
-
-	if (config) {
-		err = fuse_loop_cfg_verify(config);
-		if (err)
-			return err;
-	} else {
-		/* The caller does not care about parameters - use the default */
-		config = fuse_loop_cfg_create();
-		created_config = 1;
-	}
-
 
 	memset(&mt, 0, sizeof(struct fuse_mt));
 	mt.se = se;
@@ -372,7 +317,6 @@
 	mt.numworker = 0;
 	mt.numavail = 0;
 	mt.max_idle = config->max_idle_threads;
-	mt.max_threads = config->max_threads;
 	mt.main.thread_id = pthread_self();
 	mt.main.prev = mt.main.next = &mt.main;
 	sem_init(&mt.finish, 0, 0);
@@ -403,112 +347,15 @@
 	if(se->error != 0)
 		err = se->error;
 	fuse_session_reset(se);
-
-	if (created_config) {
-		fuse_loop_cfg_destroy(config);
-		config = NULL;
-	}
-
 	return err;
 }
 
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config_v1 *config_v1);
-FUSE_SYMVER("fuse_session_loop_mt_32", "fuse_session_loop_mt@FUSE_3.2")
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config_v1 *config_v1)
-{
-	int err;
-	struct fuse_loop_config *config = NULL;
-
-	if (config_v1 != NULL) {
-		/* convert the given v1 config */
-		config = fuse_loop_cfg_create();
-		if (config == NULL)
-			return ENOMEM;
-
-		fuse_loop_cfg_convert(config, config_v1);
-	}
-
-	err = fuse_session_loop_mt_312(se, config);
-
-	fuse_loop_cfg_destroy(config);
-
-	return err;
-}
-
-
 int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
 FUSE_SYMVER("fuse_session_loop_mt_31", "fuse_session_loop_mt@FUSE_3.0")
 int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd)
 {
-	int err;
-	struct fuse_loop_config *config = fuse_loop_cfg_create();
-	if (clone_fd > 0)
-		 fuse_loop_cfg_set_clone_fd(config, clone_fd);
-	err = fuse_session_loop_mt_312(se, config);
-
-	fuse_loop_cfg_destroy(config);
-
-	return err;
+	struct fuse_loop_config config;
+	config.clone_fd = clone_fd;
+	config.max_idle_threads = 10;
+	return fuse_session_loop_mt_32(se, &config);
 }
-
-struct fuse_loop_config *fuse_loop_cfg_create(void)
-{
-	struct fuse_loop_config *config = calloc(1, sizeof(*config));
-	if (config == NULL)
-		return NULL;
-
-	config->version_id       = FUSE_LOOP_MT_V2_IDENTIFIER;
-	config->max_idle_threads = FUSE_LOOP_MT_DEF_IDLE_THREADS;
-	config->max_threads      = FUSE_LOOP_MT_DEF_MAX_THREADS;
-	config->clone_fd         = FUSE_LOOP_MT_DEF_CLONE_FD;
-
-	return config;
-}
-
-void fuse_loop_cfg_destroy(struct fuse_loop_config *config)
-{
-	free(config);
-}
-
-int fuse_loop_cfg_verify(struct fuse_loop_config *config)
-{
-	if (config->version_id != FUSE_LOOP_MT_V2_IDENTIFIER)
-		return -EINVAL;
-
-	return 0;
-}
-
-void fuse_loop_cfg_convert(struct fuse_loop_config *config,
-			   struct fuse_loop_config_v1 *v1_conf)
-{
-	fuse_loop_cfg_set_idle_threads(config, v1_conf->max_idle_threads);
-
-	fuse_loop_cfg_set_clone_fd(config, v1_conf->clone_fd);
-}
-
-void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config,
-				    unsigned int value)
-{
-	if (value > FUSE_LOOP_MT_MAX_THREADS) {
-		if (value != UINT_MAX)
-			fuse_log(FUSE_LOG_ERR,
-				 "Ignoring invalid max threads value "
-				 "%u > max (%u).\n", value,
-				 FUSE_LOOP_MT_MAX_THREADS);
-		return;
-	}
-	config->max_idle_threads = value;
-}
-
-void fuse_loop_cfg_set_max_threads(struct fuse_loop_config *config,
-				   unsigned int value)
-{
-	config->max_threads = value;
-}
-
-void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config,
-				unsigned int value)
-{
-	config->clone_fd = value;
-}
-
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index e53f8a1..00567f4 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -11,7 +11,7 @@
 
 #define _GNU_SOURCE
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_kernel.h"
 #include "fuse_opt.h"
@@ -124,7 +124,6 @@
 
 static void destroy_req(fuse_req_t req)
 {
-	assert(req->ch == NULL);
 	pthread_mutex_destroy(&req->lock);
 	free(req);
 }
@@ -187,15 +186,8 @@
 		}
 	}
 
-	ssize_t res;
-	if (se->io != NULL)
-		/* se->io->writev is never NULL if se->io is not NULL as
-		specified by fuse_session_custom_io()*/
-		res = se->io->writev(ch ? ch->fd : se->fd, iov, count,
-					   se->userdata);
-	else
-		res = writev(ch ? ch->fd : se->fd, iov, count);
-
+	ssize_t res = writev(ch ? ch->fd : se->fd,
+			     iov, count);
 	int err = errno;
 
 	if (res == -1) {
@@ -214,12 +206,7 @@
 {
 	struct fuse_out_header out;
 
-#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 32
-	const char *str = strerrordesc_np(error * -1);
-	if ((str == NULL && error != 0) || error > 0) {
-#else
 	if (error <= -1000 || error > 0) {
-#endif
 		fuse_log(FUSE_LOG_ERR, "fuse: bad error value: %i\n",	error);
 		error = -ERANGE;
 	}
@@ -398,19 +385,10 @@
 }
 
 static void fill_open(struct fuse_open_out *arg,
-		      const struct fuse_file_info *f,
-		      int use_upstream_passthrough)
+		      const struct fuse_file_info *f)
 {
 	arg->fh = f->fh;
-	if (use_upstream_passthrough) {
-		if (f->backing_id > 0) {
-			arg->backing_id = f->backing_id;
-			arg->open_flags |= FOPEN_PASSTHROUGH;
-		}
-	} else {
-		arg->passthrough_fh = f->passthrough_fh;
-	}
-
+	arg->passthrough_fh = f->passthrough_fh;
 	if (f->direct_io)
 		arg->open_flags |= FOPEN_DIRECT_IO;
 	if (f->keep_cache)
@@ -419,10 +397,6 @@
 		arg->open_flags |= FOPEN_CACHE_DIR;
 	if (f->nonseekable)
 		arg->open_flags |= FOPEN_NONSEEKABLE;
-	if (f->noflush)
-		arg->open_flags |= FOPEN_NOFLUSH;
-	if (f->parallel_direct_writes)
-		arg->open_flags |= FOPEN_PARALLEL_DIRECT_WRITES;
 }
 
 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param* e) {
@@ -477,7 +451,7 @@
 
 	memset(buf, 0, sizeof(buf));
 	fill_entry(earg, e);
-	fill_open(oarg, f, req->se->conn.capable & FUSE_CAP_PASSTHROUGH_UPSTREAM);
+	fill_open(oarg, f);
 	return send_reply_ok(req, buf,
 			     entrysize + sizeof(struct fuse_open_out));
 }
@@ -504,8 +478,8 @@
 
 int fuse_reply_canonical_path(fuse_req_t req, const char *path)
 {
-	// The kernel expects a buffer containing the null terminator for this op
-	// So we add the null terminator size to strlen
+        // The kernel expects a buffer containing the null terminator for this op
+        // So we add the null terminator size to strlen
 	return send_reply_ok(req, path, strlen(path) + 1);
 }
 
@@ -531,8 +505,6 @@
 	static sig_atomic_t passthrough_version = FUSE_PASSTHROUGH_API_STABLE;
 	int ret = 0; /* values <= 0 represent errors in FUSE passthrough */
 
-	if (!(req->se->conn.capable & FUSE_CAP_PASSTHROUGH))
-		return -ENOTTY;
 	/*
 	 * The interface of FUSE passthrough is still unstable in the kernel,
 	 * so the following solution is to search for the most updated API
@@ -578,30 +550,6 @@
 
 	if (ret <= 0)
 		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable: %s\n", strerror(errno));
-	return ret;
-}
-
-int fuse_passthrough_open(fuse_req_t req, int fd)
-{
-	struct fuse_backing_map map = { .fd = fd };
-	int ret;
-
-	ret = ioctl(req->se->fd, FUSE_DEV_IOC_BACKING_OPEN, &map);
-	if (ret <= 0) {
-		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_open: %s\n", strerror(errno));
-		return 0;
-	}
-
-	return ret;
-}
-
-int fuse_passthrough_close(fuse_req_t req, int backing_id)
-{
-	int ret;
-
-	ret = ioctl(req->se->fd, FUSE_DEV_IOC_BACKING_CLOSE, &backing_id);
-	if (ret < 0)
-		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_close: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -611,7 +559,7 @@
 	struct fuse_open_out arg;
 
 	memset(&arg, 0, sizeof(arg));
-	fill_open(&arg, f, req->se->conn.capable & FUSE_CAP_PASSTHROUGH_UPSTREAM);
+	fill_open(&arg, f);
 	return send_reply_ok(req, &arg, sizeof(arg));
 }
 
@@ -971,14 +919,8 @@
 	    (se->conn.want & FUSE_CAP_SPLICE_MOVE))
 		splice_flags |= SPLICE_F_MOVE;
 
-	if (se->io != NULL && se->io->splice_send != NULL) {
-		res = se->io->splice_send(llp->pipe[0], NULL,
-						  ch ? ch->fd : se->fd, NULL, out->len,
-					  	  splice_flags, se->userdata);
-	} else {
-		res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd, NULL,
-			       out->len, splice_flags);
-	}
+	res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd,
+		     NULL, out->len, splice_flags);
 	if (res == -1) {
 		res = -errno;
 		perror("fuse: splice from pipe");
@@ -1355,8 +1297,6 @@
 			FUSE_SET_ATTR_SIZE	|
 			FUSE_SET_ATTR_ATIME	|
 			FUSE_SET_ATTR_MTIME	|
-			FUSE_SET_ATTR_KILL_SUID |
-			FUSE_SET_ATTR_KILL_SGID |
 			FUSE_SET_ATTR_ATIME_NOW	|
 			FUSE_SET_ATTR_MTIME_NOW |
 			FUSE_SET_ATTR_CTIME;
@@ -1523,8 +1463,6 @@
 
 	if (req->se->op.open)
 		req->se->op.open(req, nodeid, &fi);
-	else if (req->se->conn.want & FUSE_CAP_NO_OPEN_SUPPORT)
-		fuse_reply_err(req, ENOSYS);
 	else
 		fuse_reply_open(req, &fi);
 }
@@ -1681,8 +1619,6 @@
 
 	if (req->se->op.opendir)
 		req->se->op.opendir(req, nodeid, &fi);
-	else if (req->se->conn.want & FUSE_CAP_NO_OPENDIR_SUPPORT)
-		fuse_reply_err(req, ENOSYS);
 	else
 		fuse_reply_open(req, &fi);
 }
@@ -1935,9 +1871,8 @@
 
 			pthread_mutex_lock(&se->lock);
 			curr->ctr--;
-			if (!curr->ctr) {
+			if (!curr->ctr)
 				destroy_req(curr);
-			}
 
 			return 1;
 		}
@@ -1963,11 +1898,9 @@
 	req->u.i.unique = arg->unique;
 
 	pthread_mutex_lock(&se->lock);
-	if (find_interrupted(se, req)) {
-		fuse_chan_put(req->ch);
-		req->ch = NULL;
+	if (find_interrupted(se, req))
 		destroy_req(req);
-	} else
+	else
 		list_add_req(req, &se->interrupts);
 	pthread_mutex_unlock(&se->lock);
 }
@@ -1982,9 +1915,7 @@
 		if (curr->u.i.unique == req->unique) {
 			req->interrupted = 1;
 			list_del_req(curr);
-			fuse_chan_put(curr->ch);
-			curr->ch = NULL;
-			destroy_req(curr);
+			free(curr);
 			return NULL;
 		}
 	}
@@ -2128,8 +2059,8 @@
 	struct fuse_session *se = req->se;
 	size_t bufsize = se->bufsize;
 	size_t outargsize = sizeof(outarg);
-	uint64_t inargflags = 0;
-	uint64_t outargflags = 0;
+	int extended_flags;
+
 	(void) nodeid;
 	if (se->debug) {
 		fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor);
@@ -2148,6 +2079,10 @@
 	outarg.major = FUSE_KERNEL_VERSION;
 	outarg.minor = FUSE_KERNEL_MINOR_VERSION;
 
+	extended_flags = arg->major > 7 || (arg->major == 7 && arg->minor >= 36);
+	fuse_log(FUSE_LOG_DEBUG, "fuse: protocol version: %u.%u, extended flags: %d\n",
+		arg->major, arg->minor, extended_flags);
+
 	if (arg->major < 7) {
 		fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n",
 			arg->major, arg->minor);
@@ -2164,50 +2099,45 @@
 	if (arg->minor >= 6) {
 		if (arg->max_readahead < se->conn.max_readahead)
 			se->conn.max_readahead = arg->max_readahead;
-		inargflags = arg->flags;
-		if (inargflags & FUSE_INIT_EXT)
-			inargflags = inargflags | (uint64_t) arg->flags2 << 32;
-		if (inargflags & FUSE_ASYNC_READ)
+		if (arg->flags & FUSE_ASYNC_READ)
 			se->conn.capable |= FUSE_CAP_ASYNC_READ;
-		if (inargflags & FUSE_POSIX_LOCKS)
+		if (arg->flags & FUSE_POSIX_LOCKS)
 			se->conn.capable |= FUSE_CAP_POSIX_LOCKS;
-		if (inargflags & FUSE_ATOMIC_O_TRUNC)
+		if (arg->flags & FUSE_ATOMIC_O_TRUNC)
 			se->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
-		if (inargflags & FUSE_EXPORT_SUPPORT)
+		if (arg->flags & FUSE_EXPORT_SUPPORT)
 			se->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
-		if (inargflags & FUSE_DONT_MASK)
+		if (arg->flags & FUSE_DONT_MASK)
 			se->conn.capable |= FUSE_CAP_DONT_MASK;
-		if (inargflags & FUSE_FLOCK_LOCKS)
+		if (arg->flags & FUSE_FLOCK_LOCKS)
 			se->conn.capable |= FUSE_CAP_FLOCK_LOCKS;
-		if (inargflags & FUSE_AUTO_INVAL_DATA)
+		if (arg->flags & FUSE_AUTO_INVAL_DATA)
 			se->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA;
-		if (inargflags & FUSE_DO_READDIRPLUS)
+		if (arg->flags & FUSE_DO_READDIRPLUS)
 			se->conn.capable |= FUSE_CAP_READDIRPLUS;
-		if (inargflags & FUSE_READDIRPLUS_AUTO)
+		if (arg->flags & FUSE_READDIRPLUS_AUTO)
 			se->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO;
-		if (inargflags & FUSE_ASYNC_DIO)
+		if (arg->flags & FUSE_ASYNC_DIO)
 			se->conn.capable |= FUSE_CAP_ASYNC_DIO;
-		if (inargflags & FUSE_WRITEBACK_CACHE)
+		if (arg->flags & FUSE_WRITEBACK_CACHE)
 			se->conn.capable |= FUSE_CAP_WRITEBACK_CACHE;
-		if (inargflags & FUSE_NO_OPEN_SUPPORT)
+		if (arg->flags & FUSE_NO_OPEN_SUPPORT)
 			se->conn.capable |= FUSE_CAP_NO_OPEN_SUPPORT;
-		if (inargflags & FUSE_PARALLEL_DIROPS)
+		if (arg->flags & FUSE_PARALLEL_DIROPS)
 			se->conn.capable |= FUSE_CAP_PARALLEL_DIROPS;
-		if (inargflags & FUSE_POSIX_ACL)
+		if (arg->flags & FUSE_POSIX_ACL)
 			se->conn.capable |= FUSE_CAP_POSIX_ACL;
-		if (inargflags & FUSE_HANDLE_KILLPRIV)
+		if (arg->flags & FUSE_HANDLE_KILLPRIV)
 			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
-		if (inargflags & FUSE_HANDLE_KILLPRIV_V2)
-			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2;
-		if (inargflags & FUSE_CACHE_SYMLINKS)
+		if (arg->flags & FUSE_CACHE_SYMLINKS)
 			se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS;
-		if (inargflags & FUSE_NO_OPENDIR_SUPPORT)
+		if (arg->flags & FUSE_NO_OPENDIR_SUPPORT)
 			se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT;
-		if (inargflags & FUSE_EXPLICIT_INVAL_DATA)
+		if (arg->flags & FUSE_EXPLICIT_INVAL_DATA)
 			se->conn.capable |= FUSE_CAP_EXPLICIT_INVAL_DATA;
-		if (inargflags & FUSE_SETXATTR_EXT)
+		if (arg->flags & FUSE_SETXATTR_EXT)
 			se->conn.capable |= FUSE_CAP_SETXATTR_EXT;
-		if (!(inargflags & FUSE_MAX_PAGES)) {
+		if (!(arg->flags & FUSE_MAX_PAGES)) {
 			size_t max_bufsize =
 				FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize()
 				+ FUSE_BUFFER_HEADER_SIZE;
@@ -2215,17 +2145,11 @@
 				bufsize = max_bufsize;
 			}
 		}
-		if (inargflags & FUSE_DIRECT_IO_ALLOW_MMAP)
-			se->conn.capable |= FUSE_CAP_DIRECT_IO_ALLOW_MMAP;
-		if (arg->minor >= 38 || (inargflags & FUSE_HAS_EXPIRE_ONLY))
-			se->conn.capable |= FUSE_CAP_EXPIRE_ONLY;
-		if (inargflags & FUSE_PASSTHROUGH_UPSTREAM)
-			se->conn.capable |= FUSE_CAP_PASSTHROUGH_UPSTREAM;
-		if (inargflags & FUSE_INIT_EXT) {
-			if (inargflags & (1ULL << 63))
+		if (extended_flags) {
+			if (arg->flags2 & (1 << 31))
 				se->conn.capable |= FUSE_CAP_PASSTHROUGH;
 		} else {
-			if (inargflags & (1 << 31))
+			if (arg->flags & (1 << 31))
 				se->conn.capable |= FUSE_CAP_PASSTHROUGH;
 		}
 	} else {
@@ -2235,13 +2159,9 @@
 	if (se->conn.proto_minor >= 14) {
 #ifdef HAVE_SPLICE
 #ifdef HAVE_VMSPLICE
-		if ((se->io == NULL) || (se->io->splice_send != NULL)) {
-			se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
-		}
+		se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
 #endif
-		if ((se->io == NULL) || (se->io->splice_receive != NULL)) {
-			se->conn.capable |= FUSE_CAP_SPLICE_READ;
-		}
+		se->conn.capable |= FUSE_CAP_SPLICE_READ;
 #endif
 	}
 	if (se->conn.proto_minor >= 18)
@@ -2258,7 +2178,9 @@
 	if ((cond) && (se->conn.capable & (cap))) \
 		se->conn.want |= (cap)
 	LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_READ);
+	LL_SET_DEFAULT(1, FUSE_CAP_PARALLEL_DIROPS);
 	LL_SET_DEFAULT(1, FUSE_CAP_AUTO_INVAL_DATA);
+	LL_SET_DEFAULT(1, FUSE_CAP_HANDLE_KILLPRIV);
 	LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_DIO);
 	LL_SET_DEFAULT(1, FUSE_CAP_IOCTL_DIR);
 	LL_SET_DEFAULT(1, FUSE_CAP_ATOMIC_O_TRUNC);
@@ -2269,12 +2191,6 @@
 	LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS);
 	LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir,
 		       FUSE_CAP_READDIRPLUS_AUTO);
-
-	/* This could safely become default, but libfuse needs an API extension
-	 * to support it
-	 * LL_SET_DEFAULT(1, FUSE_CAP_SETXATTR_EXT);
-	 */
-
 	se->conn.time_gran = 1;
 	
 	if (bufsize < FUSE_MIN_READ_BUFFER) {
@@ -2284,13 +2200,13 @@
 	}
 	se->bufsize = bufsize;
 
+	if (se->conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE)
+		se->conn.max_write = bufsize - FUSE_BUFFER_HEADER_SIZE;
+
 	se->got_init = 1;
 	if (se->op.init)
 		se->op.init(se->userdata, &se->conn);
 
-	if (se->conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE)
-		se->conn.max_write = bufsize - FUSE_BUFFER_HEADER_SIZE;
-
 	if (se->conn.want & (~se->conn.capable)) {
 		fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities "
 			"0x%x that are not supported by kernel, aborting.\n",
@@ -2319,69 +2235,55 @@
 		outarg.flags |= FUSE_MAX_PAGES;
 		outarg.max_pages = (se->conn.max_write - 1) / getpagesize() + 1;
 	}
-	outargflags = outarg.flags;
+
 	/* Always enable big writes, this is superseded
 	   by the max_write option */
-	outargflags |= FUSE_BIG_WRITES;
+	outarg.flags |= FUSE_BIG_WRITES;
 
 	if (se->conn.want & FUSE_CAP_ASYNC_READ)
-		outargflags |= FUSE_ASYNC_READ;
+		outarg.flags |= FUSE_ASYNC_READ;
 	if (se->conn.want & FUSE_CAP_POSIX_LOCKS)
-		outargflags |= FUSE_POSIX_LOCKS;
+		outarg.flags |= FUSE_POSIX_LOCKS;
 	if (se->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
-		outargflags |= FUSE_ATOMIC_O_TRUNC;
+		outarg.flags |= FUSE_ATOMIC_O_TRUNC;
 	if (se->conn.want & FUSE_CAP_EXPORT_SUPPORT)
-		outargflags |= FUSE_EXPORT_SUPPORT;
+		outarg.flags |= FUSE_EXPORT_SUPPORT;
 	if (se->conn.want & FUSE_CAP_DONT_MASK)
-		outargflags |= FUSE_DONT_MASK;
+		outarg.flags |= FUSE_DONT_MASK;
 	if (se->conn.want & FUSE_CAP_FLOCK_LOCKS)
-		outargflags |= FUSE_FLOCK_LOCKS;
+		outarg.flags |= FUSE_FLOCK_LOCKS;
 	if (se->conn.want & FUSE_CAP_AUTO_INVAL_DATA)
-		outargflags |= FUSE_AUTO_INVAL_DATA;
+		outarg.flags |= FUSE_AUTO_INVAL_DATA;
 	if (se->conn.want & FUSE_CAP_READDIRPLUS)
-		outargflags |= FUSE_DO_READDIRPLUS;
+		outarg.flags |= FUSE_DO_READDIRPLUS;
 	if (se->conn.want & FUSE_CAP_READDIRPLUS_AUTO)
-		outargflags |= FUSE_READDIRPLUS_AUTO;
+		outarg.flags |= FUSE_READDIRPLUS_AUTO;
 	if (se->conn.want & FUSE_CAP_ASYNC_DIO)
-		outargflags |= FUSE_ASYNC_DIO;
+		outarg.flags |= FUSE_ASYNC_DIO;
 	if (se->conn.want & FUSE_CAP_WRITEBACK_CACHE)
-		outargflags |= FUSE_WRITEBACK_CACHE;
+		outarg.flags |= FUSE_WRITEBACK_CACHE;
 	if (se->conn.want & FUSE_CAP_PARALLEL_DIROPS)
-		outargflags |= FUSE_PARALLEL_DIROPS;
+		outarg.flags |= FUSE_PARALLEL_DIROPS;
 	if (se->conn.want & FUSE_CAP_POSIX_ACL)
-		outargflags |= FUSE_POSIX_ACL;
-	if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV)
-		outargflags |= FUSE_HANDLE_KILLPRIV;
-	if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV_V2)
-		outargflags |= FUSE_HANDLE_KILLPRIV_V2;
-	if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
-		outargflags |= FUSE_CACHE_SYMLINKS;
-	if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)
-		outargflags |= FUSE_EXPLICIT_INVAL_DATA;
-	if (se->conn.want & FUSE_CAP_SETXATTR_EXT)
-		outargflags |= FUSE_SETXATTR_EXT;
-	if (se->conn.want & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
-		outargflags |= FUSE_DIRECT_IO_ALLOW_MMAP;
-	if (se->conn.want & FUSE_CAP_PASSTHROUGH_UPSTREAM) {
-		outargflags |= FUSE_PASSTHROUGH_UPSTREAM;
-		/*
-		 * outarg.max_stack_depth includes the fuse stack layer,
-		 * so it is one more than max_backing_stack_depth.
-		 */
-		outarg.max_stack_depth = se->conn.max_backing_stack_depth + 1;
-	}
+		outarg.flags |= FUSE_POSIX_ACL;
 	if (se->conn.want & FUSE_CAP_PASSTHROUGH) {
-		if (inargflags & FUSE_INIT_EXT)
-			outargflags |= (1ULL << 63);
+		if (extended_flags)
+			outarg.flags2 |= (1 << 31);
 		else
-			outargflags |= (1 << 31);
+			outarg.flags |= (1 << 31);
 	}
-	if (inargflags & FUSE_INIT_EXT) {
-		outargflags |= FUSE_INIT_EXT;
-		outarg.flags2 = outargflags >> 32;
-	}
+	if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
+		outarg.flags |= FUSE_CACHE_SYMLINKS;
+	if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)
+		outarg.flags |= FUSE_EXPLICIT_INVAL_DATA;
+	if (se->conn.want & FUSE_CAP_SETXATTR_EXT)
+		outarg.flags |= FUSE_SETXATTR_EXT;
 
-	outarg.flags = outargflags;
+	if (extended_flags) {
+		if (arg->flags & FUSE_INIT_EXT) {
+			outarg.flags |= FUSE_INIT_EXT;
+		}
+	}
 
 	outarg.max_readahead = se->conn.max_readahead;
 	outarg.max_write = se->conn.max_write;
@@ -2413,9 +2315,6 @@
 			outarg.congestion_threshold);
 		fuse_log(FUSE_LOG_DEBUG, "   time_gran=%u\n",
 			outarg.time_gran);
-		if (se->conn.want & FUSE_CAP_PASSTHROUGH)
-			fuse_log(FUSE_LOG_DEBUG, "   max_stack_depth=%u\n",
-				outarg.max_stack_depth);
 	}
 	if (arg->minor < 5)
 		outargsize = FUSE_COMPAT_INIT_OUT_SIZE;
@@ -2433,7 +2332,6 @@
 	(void) inarg;
 
 	se->got_destroy = 1;
-	se->got_init = 0;
 	if (se->op.destroy)
 		se->op.destroy(se->userdata);
 
@@ -2540,43 +2438,21 @@
 	return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
 }
 
-/**
- * Notify parent attributes and the dentry matching parent/name
- * 
- * Underlying base function for fuse_lowlevel_notify_inval_entry() and
- * fuse_lowlevel_notify_expire_entry().
- * 
- * @warning
- * Only checks if fuse_lowlevel_notify_inval_entry() is supported by
- * the kernel. All other flags will fall back to 
- * fuse_lowlevel_notify_inval_entry() if not supported!
- * DO THE PROPER CHECKS IN THE DERIVED FUNCTION!
- *
- * @param se the session object
- * @param parent inode number
- * @param name file name
- * @param namelen strlen() of file name
- * @param flags flags to control if the entry should be expired or invalidated
- * @return zero for success, -errno for failure
-*/
-static int fuse_lowlevel_notify_entry(struct fuse_session *se, fuse_ino_t parent,
-							const char *name, size_t namelen,
-							enum fuse_notify_entry_flags flags)
+int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
+				     const char *name, size_t namelen)
 {
 	struct fuse_notify_inval_entry_out outarg;
 	struct iovec iov[3];
 
 	if (!se)
 		return -EINVAL;
-
+	
 	if (se->conn.proto_minor < 12)
 		return -ENOSYS;
 
 	outarg.parent = parent;
 	outarg.namelen = namelen;
-	outarg.flags = 0;
-	if (flags & FUSE_LL_EXPIRE_ONLY)
-		outarg.flags |= FUSE_EXPIRE_ONLY;
+	outarg.padding = 0;
 
 	iov[1].iov_base = &outarg;
 	iov[1].iov_len = sizeof(outarg);
@@ -2586,25 +2462,6 @@
 	return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
 }
 
-int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
-						 const char *name, size_t namelen)
-{
-	return fuse_lowlevel_notify_entry(se, parent, name, namelen, FUSE_LL_INVALIDATE);
-}
-
-int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent,
-							const char *name, size_t namelen)
-{
-	if (!se)
-		return -EINVAL;
-
-	if (!(se->conn.capable & FUSE_CAP_EXPIRE_ONLY))
-		return -ENOSYS;
-
-	return fuse_lowlevel_notify_entry(se, parent, name, namelen, FUSE_LL_EXPIRE_ONLY);
-}
-
-
 int fuse_lowlevel_notify_delete(struct fuse_session *se,
 				fuse_ino_t parent, fuse_ino_t child,
 				const char *name, size_t namelen)
@@ -3103,8 +2960,6 @@
 	free(se->cuse_data);
 	if (se->fd != -1)
 		close(se->fd);
-	if (se->io != NULL)
-		free(se->io);
 	destroy_mount_opts(se->mo);
 	free(se);
 }
@@ -3154,14 +3009,8 @@
 			goto fallback;
 	}
 
-	if (se->io != NULL && se->io->splice_receive != NULL) {
-		res = se->io->splice_receive(ch ? ch->fd : se->fd, NULL,
-						     llp->pipe[1], NULL, bufsize, 0,
-						     se->userdata);
-	} else {
-		res = splice(ch ? ch->fd : se->fd, NULL, llp->pipe[1], NULL,
-				 bufsize, 0);
-	}
+	res = splice(ch ? ch->fd : se->fd,
+		     NULL, llp->pipe[1], NULL, bufsize, 0);
 	err = errno;
 
 	if (fuse_session_exited(se))
@@ -3247,14 +3096,7 @@
 	}
 
 restart:
-	if (se->io != NULL) {
-		/* se->io->read is never NULL if se->io is not NULL as
-		specified by fuse_session_custom_io()*/
-		res = se->io->read(ch ? ch->fd : se->fd, buf->mem, se->bufsize,
-					 se->userdata);
-	} else {
-		res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
-	}
+	res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
 	err = errno;
 
 	if (fuse_session_exited(se))
@@ -3288,12 +3130,9 @@
 	return res;
 }
 
-FUSE_SYMVER("_fuse_session_new_317", "_fuse_session_new@@FUSE_3.17")
-struct fuse_session *_fuse_session_new_317(struct fuse_args *args,
-					  const struct fuse_lowlevel_ops *op,
-					  size_t op_size,
-					  struct libfuse_version *version,
-					  void *userdata)
+struct fuse_session *fuse_session_new(struct fuse_args *args,
+				      const struct fuse_lowlevel_ops *op,
+				      size_t op_size, void *userdata)
 {
 	int err;
 	struct fuse_session *se;
@@ -3372,14 +3211,6 @@
 	se->userdata = userdata;
 
 	se->mo = mo;
-
-	/* Fuse server application should pass the version it was compiled
-	 * against and pass it. If a libfuse version accidentally introduces an
-	 * ABI incompatibility, it might be possible to 'fix' that at run time,
-	 * by checking the version numbers.
-	 */
-	se->version = *version;
-
 	return se;
 
 out5:
@@ -3395,56 +3226,6 @@
 	return NULL;
 }
 
-struct fuse_session *fuse_session_new_30(struct fuse_args *args,
-					  const struct fuse_lowlevel_ops *op,
-					  size_t op_size,
-					  void *userdata);
-FUSE_SYMVER("fuse_session_new_30", "fuse_session_new@FUSE_3.0")
-struct fuse_session *fuse_session_new_30(struct fuse_args *args,
-					  const struct fuse_lowlevel_ops *op,
-					  size_t op_size,
-					  void *userdata)
-{
-	/* unknown version */
-	struct libfuse_version version = { 0 };
-
-	return _fuse_session_new_317(args, op, op_size, &version, userdata);
-}
-
-int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io,
-			   int fd)
-{
-	if (fd < 0) {
-		fuse_log(FUSE_LOG_ERR, "Invalid file descriptor value %d passed to "
-			"fuse_session_custom_io()\n", fd);
-		return -EBADF;
-	}
-	if (io == NULL) {
-		fuse_log(FUSE_LOG_ERR, "No custom IO passed to "
-			"fuse_session_custom_io()\n");
-		return -EINVAL;
-	} else if (io->read == NULL || io->writev == NULL) {
-		/* If the user provides their own file descriptor, we can't
-		guarantee that the default behavior of the io operations made
-		in libfuse will function properly. Therefore, we enforce the
-		user to implement these io operations when using custom io. */
-		fuse_log(FUSE_LOG_ERR, "io passed to fuse_session_custom_io() must "
-			"implement both io->read() and io->writev\n");
-		return -EINVAL;
-	}
-
-	se->io = malloc(sizeof(struct fuse_custom_io));
-	if (se->io == NULL) {
-		fuse_log(FUSE_LOG_ERR, "Failed to allocate memory for custom io. "
-			"Error: %s\n", strerror(errno));
-		return -errno;
-	}
-
-	se->fd = fd;
-	*se->io = *io;
-	return 0;
-}
-
 int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
 {
 	int fd;
diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h
index 855edc3..f956ab7 100644
--- a/lib/fuse_misc.h
+++ b/lib/fuse_misc.h
@@ -11,11 +11,8 @@
 /*
   Versioned symbols cannot be used in some cases because it
     - not supported on MacOSX (in MachO binary format)
-
-  Note: "@@" denotes the default symbol, "@" is binary a compat version.
-
 */
-#ifdef LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS
+#ifndef __APPLE__
 # if HAVE_SYMVER_ATTRIBUTE
 #  define FUSE_SYMVER(sym1, sym2) __attribute__ ((symver (sym2)))
 # else
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index 1d3b6a1..93066b9 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -9,7 +9,7 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_opt.h"
 #include "fuse_misc.h"
diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c
index 4c1d172..4271947 100644
--- a/lib/fuse_signals.c
+++ b/lib/fuse_signals.c
@@ -8,7 +8,7 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_lowlevel.h"
 #include "fuse_i.h"
 
@@ -16,30 +16,15 @@
 #include <string.h>
 #include <signal.h>
 #include <stdlib.h>
-#include <execinfo.h>
 
 static struct fuse_session *fuse_instance;
 
-static void dump_stack(void)
-{
-#ifdef HAVE_BACKTRACE
-	const size_t backtrace_sz = 1024 * 1024;
-	void* backtrace_buffer[backtrace_sz];
-
-	int err_fd = fileno(stderr);
-
-	int trace_len = backtrace(backtrace_buffer, backtrace_sz);
-	backtrace_symbols_fd(backtrace_buffer, trace_len, err_fd);
-#endif
-}
-
 static void exit_handler(int sig)
 {
 	if (fuse_instance) {
 		fuse_session_exit(fuse_instance);
 		if(sig <= 0) {
 			fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
-			dump_stack();
 			abort();
 		}
 		fuse_instance->error = sig;
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index c06cd18..35964f3 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -3,6 +3,7 @@
 		fuse_destroy;
 		fuse_exit;
 		fuse_loop;
+		fuse_loop_mt;
 		fuse_reply_attr;
 		fuse_reply_buf;
 		fuse_reply_entry;
@@ -16,6 +17,7 @@
 		fuse_session_exit;
 		fuse_session_exited;
 		fuse_session_loop;
+		fuse_session_loop_mt;
 		fuse_session_reset;
 		fuse_session_fd;
 		fuse_opt_parse;
@@ -23,6 +25,7 @@
 		fuse_opt_add_arg;
 		fuse_opt_free_args;
 		fuse_opt_match;
+		fuse_parse_cmdline;
 		fuse_remove_signal_handlers;
 		fuse_reply_create;
 		fuse_reply_open;
@@ -33,9 +36,11 @@
 		fuse_daemonize;
 		fuse_get_session;
 		fuse_interrupted;
+		fuse_session_new;
+		fuse_main_real;
 		fuse_mount;
-		fuse_session_custom_io;
 		fuse_session_mount;
+		fuse_new;
 		fuse_opt_insert_arg;
 		fuse_reply_lock;
 		fuse_req_interrupt_func;
@@ -133,13 +138,15 @@
 	        fuse_lib_help;
 		fuse_invalidate_path;
 		fuse_new_30;
-		fuse_new_31;
+		fuse_new;
 } FUSE_3.0;
 
 FUSE_3.2 {
 	global:
+		fuse_session_loop_mt;
 		fuse_session_loop_mt_31;
 		fuse_session_loop_mt_32;
+		fuse_loop_mt;
 		fuse_loop_mt_31;
 } FUSE_3.1;
 
@@ -161,32 +168,6 @@
 		fuse_reply_canonical_path;
 } FUSE_3.3;
 
-FUSE_3.12 {
-	global:
-		fuse_session_loop_mt_312;
-		fuse_loop_mt_32;
-		fuse_loop_mt_312;
-		fuse_loop_cfg_create;
-		fuse_loop_cfg_destroy;
-		fuse_loop_cfg_set_idle_threads;
-		fuse_loop_cfg_set_max_threads;
-		fuse_loop_cfg_set_clone_fd;
-		fuse_loop_cfg_convert;
-		fuse_parse_cmdline_30;
-		fuse_parse_cmdline_312;
-		fuse_lowlevel_notify_expire_entry;
-} FUSE_3.4;
-
-FUSE_3.17 {
-	global:
-		_fuse_session_new_317;
-		_fuse_new_30;
-		_fuse_new_317;
-		fuse_main_real_317;
-		fuse_passthrough_open;
-		fuse_passthrough_close;
-} FUSE_3.12;
-
 # Local Variables:
 # indent-tabs-mode: t
 # End:
diff --git a/lib/helper.c b/lib/helper.c
index e84c857..64ff7ad 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -10,7 +10,7 @@
   See the file COPYING.LIB.
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_misc.h"
 #include "fuse_opt.h"
@@ -50,7 +50,6 @@
 #endif
 	FUSE_HELPER_OPT("clone_fd",	clone_fd),
 	FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
-	FUSE_HELPER_OPT("max_threads=%u", max_threads),
 	FUSE_OPT_END
 };
 
@@ -137,8 +136,6 @@
 	       "    -o clone_fd            use separate fuse device fd for each thread\n"
 	       "                           (may improve performance)\n"
 	       "    -o max_idle_threads    the maximum number of idle worker threads\n"
-	       "                           allowed (default: -1)\n"
-	       "    -o max_threads         the maximum number of worker threads\n"
 	       "                           allowed (default: 10)\n");
 }
 
@@ -202,16 +199,12 @@
 	return res;
 }
 
-int fuse_parse_cmdline_312(struct fuse_args *args,
-			   struct fuse_cmdline_opts *opts);
-FUSE_SYMVER("fuse_parse_cmdline_312", "fuse_parse_cmdline@@FUSE_3.12")
-int fuse_parse_cmdline_312(struct fuse_args *args,
-			   struct fuse_cmdline_opts *opts)
+int fuse_parse_cmdline(struct fuse_args *args,
+		       struct fuse_cmdline_opts *opts)
 {
 	memset(opts, 0, sizeof(struct fuse_cmdline_opts));
 
-	opts->max_idle_threads = UINT_MAX; /* new default in fuse version 3.12 */
-	opts->max_threads = 10;
+	opts->max_idle_threads = 10;
 
 	if (fuse_opt_parse(args, opts, fuse_helper_opts,
 			   fuse_helper_opt_proc) == -1)
@@ -228,27 +221,6 @@
 	return 0;
 }
 
-/**
- * struct fuse_cmdline_opts got extended in libfuse-3.12
- */
-int fuse_parse_cmdline_30(struct fuse_args *args,
-		       struct fuse_cmdline_opts *opts);
-FUSE_SYMVER("fuse_parse_cmdline_30", "fuse_parse_cmdline@FUSE_3.0")
-int fuse_parse_cmdline_30(struct fuse_args *args,
-			  struct fuse_cmdline_opts *out_opts)
-{
-	struct fuse_cmdline_opts opts;
-
-	int rc = fuse_parse_cmdline_312(args, &opts);
-	if (rc == 0) {
-		/* copy up to the size of the old pre 3.12 struct */
-		memcpy(out_opts, &opts,
-		       offsetof(struct fuse_cmdline_opts, max_idle_threads) +
-		       sizeof(opts.max_idle_threads));
-	}
-
-	return rc;
-}
 
 int fuse_daemonize(int foreground)
 {
@@ -304,17 +276,13 @@
 	return 0;
 }
 
-int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
-		   size_t op_size, struct libfuse_version *version, void *user_data);
-FUSE_SYMVER("fuse_main_real_317", "fuse_main_real@@FUSE_3.17")
-int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
-		   size_t op_size, struct libfuse_version *version, void *user_data)
+int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
+		   size_t op_size, void *user_data)
 {
 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
 	struct fuse *fuse;
 	struct fuse_cmdline_opts opts;
 	int res;
-	struct fuse_loop_config *loop_config = NULL;
 
 	if (fuse_parse_cmdline(&args, &opts) != 0)
 		return 1;
@@ -344,7 +312,8 @@
 		goto out1;
 	}
 
-	fuse = _fuse_new(&args, op, op_size, version, user_data);
+
+	fuse = fuse_new_31(&args, op, op_size, user_data);
 	if (fuse == NULL) {
 		res = 3;
 		goto out1;
@@ -369,20 +338,13 @@
 	if (opts.singlethread)
 		res = fuse_loop(fuse);
 	else {
-		loop_config = fuse_loop_cfg_create();
-		if (loop_config == NULL) {
-			res = 7;
-			goto out3;
-		}
-
-		fuse_loop_cfg_set_clone_fd(loop_config, opts.clone_fd);
-
-		fuse_loop_cfg_set_idle_threads(loop_config, opts.max_idle_threads);
-		fuse_loop_cfg_set_max_threads(loop_config, opts.max_threads);
-		res = fuse_loop_mt(fuse, loop_config);
+		struct fuse_loop_config loop_config;
+		loop_config.clone_fd = opts.clone_fd;
+		loop_config.max_idle_threads = opts.max_idle_threads;
+		res = fuse_loop_mt_32(fuse, &loop_config);
 	}
 	if (res)
-		res = 8;
+		res = 7;
 
 	fuse_remove_signal_handlers(se);
 out3:
@@ -390,22 +352,11 @@
 out2:
 	fuse_destroy(fuse);
 out1:
-	fuse_loop_cfg_destroy(loop_config);
 	free(opts.mountpoint);
 	fuse_opt_free_args(&args);
 	return res;
 }
 
-int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
-		      size_t op_size, void *user_data);
-FUSE_SYMVER("fuse_main_real_30", "fuse_main_real@FUSE_3.0")
-int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
-		      size_t op_size, void *user_data)
-{
-	struct libfuse_version version = { 0 };
-
-	return fuse_main_real_317(argc, argv, op, op_size, &version, user_data);
-}
 
 void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
 			       struct fuse_conn_info *conn)
diff --git a/lib/libfuse_config.h b/lib/libfuse_config.h
deleted file mode 100644
index 46cf797..0000000
--- a/lib/libfuse_config.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Autogenerated by the Meson build system.
- * Do not edit, your changes will be lost.
- */
-
-#pragma once
-
-#define FUSE_HOTFIX_VERSION 2
-
-#define FUSE_MAJOR_VERSION 3
-
-#define FUSE_MINOR_VERSION 16
-
diff --git a/lib/meson.build b/lib/meson.build
index 9044630..98461d8 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -2,7 +2,7 @@
                    'fuse_lowlevel.c', 'fuse_misc.h', 'fuse_opt.c',
                    'fuse_signals.c', 'buffer.c', 'cuse_lowlevel.c',
                    'helper.c', 'modules/subdir.c', 'mount_util.c',
-                   'fuse_log.c', 'compat.c' ]
+                   'fuse_log.c' ]
 
 if host_machine.system().startswith('linux')
    libfuse_sources += [ 'mount.c' ]
@@ -11,7 +11,7 @@
 endif
 
 deps = [ thread_dep ]
-if private_cfg.get('HAVE_ICONV')
+if cfg.get('HAVE_ICONV')
    libfuse_sources += [ 'modules/iconv.c' ]
    libiconv = cc.find_library('iconv', required: false)
    if libiconv.found()
@@ -37,7 +37,7 @@
                   soversion: '3', include_directories: include_dirs,
                   dependencies: deps, install: true,
                   link_depends: 'fuse_versionscript',
-                  c_args: [ '-DFUSE_USE_VERSION=312',
+                  c_args: [ '-DFUSE_USE_VERSION=35',
                             '-DFUSERMOUNT_DIR="@0@"'.format(fusermount_path) ],
                   link_args: ['-Wl,--version-script,' + meson.current_source_dir()
                               + '/fuse_versionscript' ])
diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c
index a0bf72b..0ec3c2b 100644
--- a/lib/modules/iconv.c
+++ b/lib/modules/iconv.c
@@ -6,7 +6,7 @@
   See the file COPYING.LIB
 */
 
-#include <fuse_config.h>
+#include <config.h>
 
 #include <fuse.h>
 #include <stdio.h>
@@ -77,13 +77,12 @@
 
 			inc = (pathlen + 1) * 4;
 			newpathlen += inc;
-			int dp = p - newpath;
 			tmp = realloc(newpath, newpathlen + 1);
 			err = -ENOMEM;
 			if (!tmp)
 				goto err;
 
-			p = tmp + dp;
+			p = tmp + (p - newpath);
 			plen += inc;
 			newpath = tmp;
 		}
diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c
index e92eb62..616c0ee 100644
--- a/lib/modules/subdir.c
+++ b/lib/modules/subdir.c
@@ -6,7 +6,7 @@
   See the file COPYING.LIB
 */
 
-#include <fuse_config.h>
+#include <config.h>
 
 #include <fuse.h>
 #include <stdio.h>
diff --git a/lib/mount.c b/lib/mount.c
index 3fbbe72..979f8d9 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -8,10 +8,7 @@
   See the file COPYING.LIB.
 */
 
-/* For environ */
-#define _GNU_SOURCE
-
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_misc.h"
 #include "fuse_opt.h"
@@ -25,12 +22,10 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <poll.h>
-#include <spawn.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/wait.h>
-
-#include "fuse_mount_compat.h"
+#include <sys/mount.h>
 
 #ifdef __NetBSD__
 #include <perfuse.h>
@@ -48,6 +43,10 @@
 #define FUSERMOUNT_PROG		"fusermount3"
 #define FUSE_COMMFD_ENV		"_FUSE_COMMFD"
 
+#ifndef HAVE_FORK
+#define fork() vfork()
+#endif
+
 #ifndef MS_DIRSYNC
 #define MS_DIRSYNC 128
 #endif
@@ -98,7 +97,6 @@
 	FUSE_OPT_KEY("rootcontext=",		KEY_KERN_OPT),
 	FUSE_OPT_KEY("max_read=",		KEY_KERN_OPT),
 	FUSE_OPT_KEY("user=",			KEY_MTAB_OPT),
-	FUSE_OPT_KEY("-n",			KEY_MTAB_OPT),
 	FUSE_OPT_KEY("-r",			KEY_RO),
 	FUSE_OPT_KEY("ro",			KEY_KERN_FLAG),
 	FUSE_OPT_KEY("rw",			KEY_KERN_FLAG),
@@ -111,57 +109,26 @@
 	FUSE_OPT_KEY("async",			KEY_KERN_FLAG),
 	FUSE_OPT_KEY("sync",			KEY_KERN_FLAG),
 	FUSE_OPT_KEY("dirsync",			KEY_KERN_FLAG),
+	FUSE_OPT_KEY("atime",			KEY_KERN_FLAG),
 	FUSE_OPT_KEY("noatime",			KEY_KERN_FLAG),
-	FUSE_OPT_KEY("nodiratime",		KEY_KERN_FLAG),
-	FUSE_OPT_KEY("nostrictatime",		KEY_KERN_FLAG),
 	FUSE_OPT_END
 };
 
-/*
- * Running fusermount by calling 'posix_spawn'
- *
- * @param out_pid might be NULL
- */
-static int fusermount_posix_spawn(posix_spawn_file_actions_t *action,
-				  char const * const argv[], pid_t *out_pid)
+static void exec_fusermount(const char *argv[])
 {
-	const char *full_path = FUSERMOUNT_DIR "/" FUSERMOUNT_PROG;
-	pid_t pid;
-
-	/* See man 7 environ for the global environ pointer */
-
-	/* first try the install path */
-	int status = posix_spawn(&pid, full_path,  action, NULL,
-				 (char * const *) argv, environ);
-	if (status != 0) {
-		/* if that fails, try a system install */
-		status = posix_spawnp(&pid, FUSERMOUNT_PROG, action, NULL,
-				      (char * const *) argv, environ);
-	}
-
-	if (status != 0) {
-		fuse_log(FUSE_LOG_ERR,
-			 "On calling fusermount posix_spawn failed: %s\n",
-			 strerror(status));
-		return -status;
-	}
-
-	if (out_pid)
-		*out_pid = pid;
-	else
-		waitpid(pid, NULL, 0);
-
-	return 0;
+	execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
+	execvp(FUSERMOUNT_PROG, (char **) argv);
 }
 
 void fuse_mount_version(void)
 {
-	char const *const argv[] = {FUSERMOUNT_PROG, "--version", NULL};
-	int status = fusermount_posix_spawn(NULL, argv, NULL);
-
-	if(status != 0)
-		fuse_log(FUSE_LOG_ERR, "Running '%s --version' failed",
-			 FUSERMOUNT_PROG);
+	int pid = fork();
+	if (!pid) {
+		const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL };
+		exec_fusermount(argv);
+		_exit(1);
+	} else if (pid != -1)
+		waitpid(pid, NULL, 0);
 }
 
 struct mount_flags {
@@ -181,10 +148,8 @@
 	{"noexec",  MS_NOEXEC,	    1},
 	{"async",   MS_SYNCHRONOUS, 0},
 	{"sync",    MS_SYNCHRONOUS, 1},
+	{"atime",   MS_NOATIME,	    0},
 	{"noatime", MS_NOATIME,	    1},
-	{"nodiratime",	    MS_NODIRATIME,	1},
-	{"norelatime",	    MS_RELATIME,	0},
-	{"nostrictatime",   MS_STRICTATIME,	0},
 #ifndef __NetBSD__
 	{"dirsync", MS_DIRSYNC,	    1},
 #endif
@@ -239,12 +204,6 @@
 
 	case KEY_MTAB_OPT:
 		return fuse_opt_add_opt(&mo->mtab_opts, arg);
-
-	/* Third party options like 'x-gvfs-notrash' */
-	case FUSE_OPT_KEY_OPT:
-		return (strncmp("x-", arg, 2) == 0) ?
-			fuse_opt_add_opt(&mo->mtab_opts, arg) :
-			1;
 	}
 
 	/* Pass through unknown options */
@@ -279,7 +238,7 @@
 
 	while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
 	if (rv == -1) {
-		fuse_log(FUSE_LOG_ERR, "recvmsg failed: %s", strerror(errno));
+		perror("recvmsg");
 		return -1;
 	}
 	if(!rv) {
@@ -299,6 +258,7 @@
 void fuse_kern_unmount(const char *mountpoint, int fd)
 {
 	int res;
+	int pid;
 
 	if (fd != -1) {
 		struct pollfd pfd;
@@ -330,86 +290,26 @@
 	if (res == 0)
 		return;
 
-	char const * const argv[] =
-		{ FUSERMOUNT_PROG, "--unmount", "--quiet", "--lazy",
-				"--", mountpoint, NULL };
-	int status = fusermount_posix_spawn(NULL, argv, NULL);
-	if(status != 0) {
-		fuse_log(FUSE_LOG_ERR, "Spawaning %s to unumount failed",
-			 FUSERMOUNT_PROG);
+	pid = fork();
+	if(pid == -1)
 		return;
+
+	if(pid == 0) {
+		const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z",
+				       "--", mountpoint, NULL };
+
+		exec_fusermount(argv);
+		_exit(1);
 	}
-}
-
-static int setup_auto_unmount(const char *mountpoint, int quiet)
-{
-	int fds[2];
-	pid_t pid;
-	int res;
-
-	if (!mountpoint) {
-		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
-		return -1;
-	}
-
-	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
-	if(res == -1) {
-		fuse_log(FUSE_LOG_ERR, "Setting up auto-unmountsocketpair() failed",
-			 strerror(errno));
-		return -1;
-	}
-
-	char arg_fd_entry[30];
-	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
-	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
-
-	char const *const argv[] = {
-		FUSERMOUNT_PROG,
-		"--auto-unmount",
-		"--",
-		mountpoint,
-		NULL,
-	};
-
-	// TODO: add error handling for all manipulations of action.
-	posix_spawn_file_actions_t action;
-	posix_spawn_file_actions_init(&action);
-
-	if (quiet) {
-		posix_spawn_file_actions_addclose(&action, 1);
-		posix_spawn_file_actions_addclose(&action, 2);
-	}
-	posix_spawn_file_actions_addclose(&action, fds[1]);
-
-	/*
-	 * auto-umount runs in the background - it is not waiting for the
-	 * process
-	 */
-	int status = fusermount_posix_spawn(&action, argv, &pid);
-
-	posix_spawn_file_actions_destroy(&action);
-
-	if(status != 0) {
-		close(fds[0]);
-		close(fds[1]);
-		fuse_log(FUSE_LOG_ERR, "fuse: Setting up auto-unmount failed");
-		return -1;
-	}
-	// passed to child now, so can close here.
-	close(fds[0]);
-
-	// Now fusermount3 will only exit when fds[1] closes automatically when our
-	// process exits.
-	return 0;
-	// Note: fds[1] is leakend and doesn't get FD_CLOEXEC
+	waitpid(pid, NULL, 0);
 }
 
 static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
 		const char *opts, int quiet)
 {
-	int fds[2];
-	pid_t pid;
+	int fds[2], pid;
 	int res;
+	int rv;
 
 	if (!mountpoint) {
 		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
@@ -418,49 +318,51 @@
 
 	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
 	if(res == -1) {
-		fuse_log(FUSE_LOG_ERR, "Running %s: socketpair() failed: %s\n",
-			 FUSERMOUNT_PROG, strerror(errno));
+		perror("fuse: socketpair() failed");
 		return -1;
 	}
 
-	char arg_fd_entry[30];
-	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
-	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
-
-	char const *const argv[] = {
-		FUSERMOUNT_PROG,
-		"-o", opts ? opts : "",
-		"--",
-		mountpoint,
-		NULL,
-	};
-
-
-	posix_spawn_file_actions_t action;
-	posix_spawn_file_actions_init(&action);
-
-	if (quiet) {
-		posix_spawn_file_actions_addclose(&action, 1);
-		posix_spawn_file_actions_addclose(&action, 2);
-	}
-	posix_spawn_file_actions_addclose(&action, fds[1]);
-
-	int status = fusermount_posix_spawn(&action, argv, &pid);
-
-	posix_spawn_file_actions_destroy(&action);
-
-	if(status != 0) {
+	pid = fork();
+	if(pid == -1) {
+		perror("fuse: fork() failed");
 		close(fds[0]);
 		close(fds[1]);
-		fuse_log(FUSE_LOG_ERR, "posix_spawnp() for %s failed",
-			 FUSERMOUNT_PROG, strerror(errno));
 		return -1;
 	}
 
-	// passed to child now, so can close here.
-	close(fds[0]);
+	if(pid == 0) {
+		char env[10];
+		const char *argv[32];
+		int a = 0;
 
-	int fd = receive_fd(fds[1]);
+		if (quiet) {
+			int fd = open("/dev/null", O_RDONLY);
+			if (fd != -1) {
+				dup2(fd, 1);
+				dup2(fd, 2);
+			}
+		}
+
+		argv[a++] = FUSERMOUNT_PROG;
+		if (opts) {
+			argv[a++] = "-o";
+			argv[a++] = opts;
+		}
+		argv[a++] = "--";
+		argv[a++] = mountpoint;
+		argv[a++] = NULL;
+
+		close(fds[1]);
+		fcntl(fds[0], F_SETFD, 0);
+		snprintf(env, sizeof(env), "%i", fds[0]);
+		setenv(FUSE_COMMFD_ENV, env, 1);
+		exec_fusermount(argv);
+		perror("fuse: failed to exec fusermount3");
+		_exit(1);
+	}
+
+	close(fds[0]);
+	rv = receive_fd(fds[1]);
 
 	if (!mo->auto_unmount) {
 		/* with auto_unmount option fusermount3 will not exit until
@@ -469,10 +371,10 @@
 		waitpid(pid, NULL, 0); /* bury zombie */
 	}
 
-	if (fd >= 0)
-		fcntl(fd, F_SETFD, FD_CLOEXEC);
+	if (rv >= 0)
+		fcntl(rv, F_SETFD, FD_CLOEXEC);
 
-	return fd;
+	return rv;
 }
 
 #ifndef O_CLOEXEC
@@ -502,6 +404,12 @@
 		return -1;
 	}
 
+	if (mo->auto_unmount) {
+		/* Tell the caller to fallback to fusermount3 because
+		   auto-unmount does not work otherwise. */
+		return -2;
+	}
+
 	fd = open(devname, O_RDWR | O_CLOEXEC);
 	if (fd == -1) {
 		if (errno == ENODEV || errno == ENOENT)
@@ -664,13 +572,7 @@
 		goto out;
 
 	res = fuse_mount_sys(mountpoint, mo, mnt_opts);
-	if (res >= 0 && mo->auto_unmount) {
-		if(0 > setup_auto_unmount(mountpoint, 0)) {
-			// Something went wrong, let's umount like in fuse_mount_sys.
-			umount2(mountpoint, MNT_DETACH); /* lazy umount */
-			res = -1;
-		}
-	} else if (res == -2) {
+	if (res == -2) {
 		if (mo->fusermount_opts &&
 		    fuse_opt_add_opt(&mnt_opts, mo->fusermount_opts) == -1)
 			goto out;
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index c9669ae..35f3634 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -8,13 +8,13 @@
   See the file COPYING.LIB.
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "fuse_i.h"
 #include "fuse_misc.h"
 #include "fuse_opt.h"
 
 #include <sys/param.h>
-#include "fuse_mount_compat.h"
+#include <sys/mount.h>
 
 #include <sys/stat.h>
 #include <sys/wait.h>
diff --git a/lib/mount_util.c b/lib/mount_util.c
index dd32276..35e9948 100644
--- a/lib/mount_util.c
+++ b/lib/mount_util.c
@@ -8,9 +8,8 @@
   See the file COPYING.LIB.
 */
 
-#include "fuse_config.h"
+#include "config.h"
 #include "mount_util.h"
-
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -28,9 +27,7 @@
 #endif
 #include <sys/stat.h>
 #include <sys/wait.h>
-
-#include "fuse_mount_compat.h"
-
+#include <sys/mount.h>
 #include <sys/param.h>
 
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
@@ -54,6 +51,7 @@
 	 * Skip mtab update if /etc/mtab:
 	 *
 	 *  - doesn't exist,
+	 *  - is a symlink,
 	 *  - is on a read-only filesystem.
 	 */
 	res = lstat(_PATH_MOUNTED, &stbuf);
@@ -64,6 +62,9 @@
 		uid_t ruid;
 		int err;
 
+		if (S_ISLNK(stbuf.st_mode))
+			return 0;
+
 		ruid = getuid();
 		if (ruid != 0)
 			setreuid(0, -1);
diff --git a/meson.build b/meson.build
index 4b570d1..8a6587b 100644
--- a/meson.build
+++ b/meson.build
@@ -1,52 +1,27 @@
-project('libfuse3', ['c'], version: '3.17.0',
-        meson_version: '>= 0.51',
+project('libfuse3', ['c'], version: '3.10.5',
+        meson_version: '>= 0.42',
         default_options: [
             'buildtype=debugoptimized',
-            'c_std=gnu11',
             'cpp_std=c++11',
             'warning_level=2',
         ])
 
-# Would be better to create the version string
-# from integers, i.e. concatenating strings instead
-# of splitting a string, but 'project' needs to be
-# the first meson.build keyword...
-version_list = meson.project_version().split('.')
-FUSE_MAJOR_VERSION = version_list[0]
-FUSE_MINOR_VERSION = version_list[1]
-FUSE_HOTFIX_VERSION = version_list[2]
 
 platform = host_machine.system()
 if platform == 'darwin'
   error('libfuse does not support OS-X.\n' +
-        'Take a look at http://osxfuse.github.io/ or the more recent\n' +
-        'https://www.fuse-t.org/ instead')
+        'Take a look at http://osxfuse.github.io/ instead')
 elif platform == 'cygwin' or platform == 'windows'
   error('libfuse does not support Windows.\n' +
         'Take a look at http://www.secfs.net/winfsp/ instead')       
 endif
 
+#
+# Feature detection
+#
+cfg = configuration_data()
 cc = meson.get_compiler('c')
 
-#
-# Feature detection, only available at libfuse compilation time,
-# but not for application linking to libfuse.
-#
-private_cfg = configuration_data()
-
-#
-# Feature detection, the resulting config file is installed
-# with the package.
-# Note: Symbols need to be care fully named, to avoid conflicts
-#       with applications linking to libfuse and including
-#       this config.
-#
-public_cfg = configuration_data()
-
-public_cfg.set('FUSE_MAJOR_VERSION', FUSE_MAJOR_VERSION)
-public_cfg.set('FUSE_MINOR_VERSION', FUSE_MINOR_VERSION)
-public_cfg.set('FUSE_HOTFIX_VERSION', FUSE_HOTFIX_VERSION)
-
 # Default includes when checking for presence of functions and
 # struct members
 include_default = '''
@@ -60,40 +35,42 @@
 '''
 args_default = [ '-D_GNU_SOURCE' ]
 
-private_cfg.set_quoted('PACKAGE_VERSION', meson.project_version())
+cfg.set_quoted('PACKAGE_VERSION', meson.project_version())
 
 # Test for presence of some functions
 test_funcs = [ 'fork', 'fstatat', 'openat', 'readlinkat', 'pipe2',
                'splice', 'vmsplice', 'posix_fallocate', 'fdatasync',
                'utimensat', 'copy_file_range', 'fallocate' ]
 foreach func : test_funcs
-    private_cfg.set('HAVE_' + func.to_upper(),
+    cfg.set('HAVE_' + func.to_upper(),
         cc.has_function(func, prefix: include_default, args: args_default))
 endforeach
-private_cfg.set('HAVE_SETXATTR', 
+cfg.set('HAVE_SETXATTR', 
         cc.has_function('setxattr', prefix: '#include <sys/xattr.h>'))
-private_cfg.set('HAVE_ICONV', 
+cfg.set('HAVE_ICONV', 
         cc.has_function('iconv', prefix: '#include <iconv.h>'))
-private_cfg.set('HAVE_BACKTRACE',
-        cc.has_function('backtrace', prefix: '#include <execinfo.h>'))
 
 # Test if structs have specific member
-private_cfg.set('HAVE_STRUCT_STAT_ST_ATIM',
+cfg.set('HAVE_STRUCT_STAT_ST_ATIM',
          cc.has_member('struct stat', 'st_atim',
                        prefix: include_default,
                        args: args_default))
-private_cfg.set('HAVE_STRUCT_STAT_ST_ATIMESPEC',
+cfg.set('HAVE_STRUCT_STAT_ST_ATIMESPEC',
          cc.has_member('struct stat', 'st_atimespec',
                        prefix: include_default,
                        args: args_default))
 
+# Write the test results into config.h (stored in build directory)
+configure_file(output: 'config.h',
+               configuration : cfg)
+
 #
 # Compiler configuration
 #
-add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-Wno-sign-compare', '-D_FILE_OFFSET_BITS=64',
+add_project_arguments('-D_REENTRANT', '-DHAVE_CONFIG_H', '-Wno-sign-compare',
                       '-Wstrict-prototypes', '-Wmissing-declarations', '-Wwrite-strings',
                       '-fno-strict-aliasing', language: 'c')
-add_project_arguments('-D_REENTRANT', '-DHAVE_LIBFUSE_PRIVATE_CONFIG_H', '-D_GNU_SOURCE', '-D_FILE_OFFSET_BITS=64',
+add_project_arguments('-D_REENTRANT', '-DHAVE_CONFIG_H', '-D_GNU_SOURCE',
                      '-Wno-sign-compare', '-Wmissing-declarations',
                      '-Wwrite-strings', '-fno-strict-aliasing', language: 'cpp')
 
@@ -113,104 +90,30 @@
      add_project_arguments('-Wno-unused-result', language: 'c')
 endif
 
-# It is hard to detect if the libc supports versioned symbols. Only gnu-libc
-# seems to provide that, but then glibc is the main target for libfuse, so
-# enable it by default
-versioned_symbols = 1
-
-# This is an attempt to detect if another libc is used.
+# gcc-10 and newer support the symver attribute which we need to use if we
+# want to support LTO
+# recent clang and gcc both support __has_attribute (and if they are too old
+# to have __has_attribute, then they are too old to support symver)
+# other compilers might not have __has_attribute, but in those cases
+# it is safe for this check to fail and for us to fallback to the old _asm_
+# method for symver. Anyway the attributes not supported by __has_attribute()
+# unfortunately return true giving a false positive. So let's try to build
+# using __attribute__ ((symver )) and see the result.
 code = '''
+__attribute__ ((symver ("test@TEST")))
+void foo(void) {
+}
+
 int main(void) {
-#if (defined(__UCLIBC__) || defined(__APPLE__))
-#error /* libc does not have versioned symbols */
-#endif
     return 0;
 }'''
-if not cc.compiles(code, args: [ '-O0' ])
-  versioned_symbols = 0
-endif
-
-# The detection can be overridden, which is useful for other (above unhandled)
-# libcs and also especially useful for testing
-if get_option('disable-libc-symbol-version')
-     versioned_symbols = 0
-endif
-
-if versioned_symbols == 1
-     message('Enabling versioned libc symbols')
-     public_cfg.set('LIBFUSE_BUILT_WITH_VERSIONED_SYMBOLS', 1)
-
-     # gcc-10 and newer support the symver attribute which we need to use if we
-     # want to support LTO
-     # recent clang and gcc both support __has_attribute (and if they are too old
-     # to have __has_attribute, then they are too old to support symver)
-     # other compilers might not have __has_attribute, but in those cases
-     # it is safe for this check to fail and for us to fallback to the old _asm_
-     # method for symver. Anyway the attributes not supported by __has_attribute()
-     # unfortunately return true giving a false positive. So let's try to build
-     # using __attribute__ ((symver )) and see the result.
-     code = '''
-     __attribute__ ((symver ("test@TEST")))
-     void foo(void) {
-     }
-
-     int main(void) {
-         return 0;
-     }'''
-     if cc.compiles(code, args: [ '-O0', '-c', '-Werror'])
-          message('Compiler supports symver attribute')
-          add_project_arguments('-DHAVE_SYMVER_ATTRIBUTE', language: 'c')
-     else
-          message('Compiler does not support symver attribute')
-     endif
+if cc.compiles(code, args: [ '-O0', '-c', '-Werror'])
+     message('Compiler supports symver attribute')
+     add_project_arguments('-DHAVE_SYMVER_ATTRIBUTE', language: 'c')
 else
-     message('Disabling versioned libc symbols')
+     message('Compiler does not support symver attribute')
 endif
 
-# Older versions of musl libc don't unescape entries in /etc/mtab
-# Try to detect this behaviour, and work around, if necessary.
-detect_getmntent_needs_unescape = '''
-#define _GNU_SOURCE
-#include <mntent.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define dir_space_tab "dir\\040space\\011tab"
-
-int main()
-{
-    const char *fake_mtab = "name " dir_space_tab " type opts 0 0\n";
-    FILE *f = fmemopen((void *)fake_mtab, strlen(fake_mtab) + 1, "r");
-    struct mntent *entp = getmntent(f);
-    fclose(f);
-    if(NULL == entp)
-        exit(EXIT_FAILURE);
-    if (0 == strcmp(entp->mnt_dir, dir_space_tab))
-        printf("needs escaping\n");
-    else
-        printf("no need to escape\n");
-}
-'''
-
-if not meson.is_cross_build()
-  result = cc.run(detect_getmntent_needs_unescape)
-  if result.compiled() and result.returncode() == 0 and result.stdout().strip() == 'needs escaping'
-    message('getmntent does not unescape')
-    add_project_arguments('-DGETMNTENT_NEEDS_UNESCAPING', language: 'c')
-  endif
-endif
-
-# Write private test results into fuse_config.h (stored in build directory)
-configure_file(output: 'fuse_config.h', configuration : private_cfg)
-
-# Write the test results, installed with the package,
-# symbols need to be properly prefixed to avoid
-# symbol (define) conflicts
-configure_file(output: 'libfuse_config.h',
-               configuration : public_cfg,
-               install: true, install_dir: join_paths(get_option('includedir'), 'fuse3'))
-
 # '.' will refer to current build directory, which contains config.h
 include_dirs = include_directories('include', 'lib', '.')
 
@@ -236,4 +139,3 @@
 foreach n : subdirs
     subdir(n)
 endforeach
-