diff --git a/SOURCES/0001-Synchronize-fuse_kernel.h.patch b/SOURCES/0001-Synchronize-fuse_kernel.h.patch
new file mode 100644
index 0000000..dd6c14c
--- /dev/null
+++ b/SOURCES/0001-Synchronize-fuse_kernel.h.patch
@@ -0,0 +1,59 @@
+From 492d3a24c13babd103fb71d44adfb8e94687db52 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Tue, 7 Jun 2022 08:27:36 +0200
+Subject: [PATCH 1/4] Synchronize fuse_kernel.h
+
+Signed-off-by: Pavel Reichl <preichl@redhat.com>
+---
+ include/fuse_kernel.h | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
+index 42fa977..b55fa8b 100644
+--- a/include/fuse_kernel.h
++++ b/include/fuse_kernel.h
+@@ -215,10 +215,12 @@ struct fuse_file_lock {
+  * FOPEN_DIRECT_IO: bypass page cache for this open file
+  * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
+  * FOPEN_NONSEEKABLE: the file is not seekable
++ * FOPEN_CACHE_DIR: allow caching this directory
+  */
+ #define FOPEN_DIRECT_IO		(1 << 0)
+ #define FOPEN_KEEP_CACHE	(1 << 1)
+ #define FOPEN_NONSEEKABLE	(1 << 2)
++#define FOPEN_CACHE_DIR		(1 << 3)
+ 
+ /**
+  * INIT request/reply flags
+@@ -244,6 +246,8 @@ struct fuse_file_lock {
+  * FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir
+  * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc
+  * FUSE_POSIX_ACL: filesystem supports posix acls
++ * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
++ * FUSE_CACHE_SYMLINKS: cache READLINK responses
+  */
+ #define FUSE_ASYNC_READ		(1 << 0)
+ #define FUSE_POSIX_LOCKS	(1 << 1)
+@@ -266,6 +270,8 @@ struct fuse_file_lock {
+ #define FUSE_PARALLEL_DIROPS    (1 << 18)
+ #define FUSE_HANDLE_KILLPRIV	(1 << 19)
+ #define FUSE_POSIX_ACL		(1 << 20)
++#define FUSE_MAX_PAGES		(1 << 22)
++#define FUSE_CACHE_SYMLINKS	(1 << 23)
+ 
+ /**
+  * CUSE INIT request/reply flags
+@@ -604,7 +610,9 @@ struct fuse_init_out {
+ 	uint16_t	congestion_threshold;
+ 	uint32_t	max_write;
+ 	uint32_t	time_gran;
+-	uint32_t	unused[9];
++	uint16_t	max_pages;
++	uint16_t	padding;
++	uint32_t	unused[8];
+ };
+ 
+ #define CUSE_INIT_INFO_MAX 4096
+-- 
+2.36.1
+
diff --git a/SOURCES/0002-fuse_lowlevel-Add-max_pages-support-384.patch b/SOURCES/0002-fuse_lowlevel-Add-max_pages-support-384.patch
new file mode 100644
index 0000000..4854850
--- /dev/null
+++ b/SOURCES/0002-fuse_lowlevel-Add-max_pages-support-384.patch
@@ -0,0 +1,130 @@
+From 5100bdc814435a1222fef6438cebcd81a3de6c73 Mon Sep 17 00:00:00 2001
+From: scosu <mpargmann@allfex.org>
+Date: Thu, 13 Jun 2019 13:59:10 +0200
+Subject: [PATCH 2/4] fuse_lowlevel: Add max_pages support (#384)
+
+Starting with kernel version 4.20 fuse supports a new property
+'max_pages' which is the maximum number of pages that can be used per
+request. This can be set via an argument during initialization.
+This new property allows writes to be larger than 128k.
+
+This patch sets the property if the matching capability is set
+(FUSE_MAX_PAGES). It will also set max_write to 1MiB. Filesystems have
+the possibility to decrease this size by setting max_write to a smaller
+size. The max_pages and bufsize fields are adjusted accordingly.
+
+Cc: Constantine Shulyupin <const@MakeLinux.com>
+Signed-off-by: Markus Pargmann <scosu@quobyte.com>
+(cherry picked from commit 027d0d17c8a4605109f09d9c988e255b64a2c19a)
+Signed-off-by: Pavel Reichl <preichl@redhat.com>
+---
+ ChangeLog.rst       |  7 +++++++
+ lib/fuse_i.h        |  6 ++++++
+ lib/fuse_lowlevel.c | 30 +++++++++++++++++++++---------
+ 3 files changed, 34 insertions(+), 9 deletions(-)
+
+diff --git a/ChangeLog.rst b/ChangeLog.rst
+index 8ea9397..411cd4a 100644
+--- a/ChangeLog.rst
++++ b/ChangeLog.rst
+@@ -1,6 +1,13 @@
+ libfuse 3.3.0 (2018-11-06)
+ ==========================
+ 
++* 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.
++
+ * The `auto_unmount` mode now works correctly in combination with
+   autofs.
+ 
+diff --git a/lib/fuse_i.h b/lib/fuse_i.h
+index cf35551..d38b630 100644
+--- a/lib/fuse_i.h
++++ b/lib/fuse_i.h
+@@ -131,3 +131,9 @@ struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *o
+ 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
++
++/* room needed in buffer to accommodate header */
++#define FUSE_BUFFER_HEADER_SIZE 0x1000
++
+diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
+index 844e797..60195e0 100644
+--- a/lib/fuse_lowlevel.c
++++ b/lib/fuse_lowlevel.c
+@@ -1882,6 +1882,14 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+ 			se->conn.capable |= FUSE_CAP_POSIX_ACL;
+ 		if (arg->flags & FUSE_HANDLE_KILLPRIV)
+ 			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
++		if (!(arg->flags & FUSE_MAX_PAGES)) {
++			size_t max_bufsize =
++				FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize()
++				+ FUSE_BUFFER_HEADER_SIZE;
++			if (bufsize > max_bufsize) {
++				bufsize = max_bufsize;
++			}
++		}
+ 	} else {
+ 		se->conn.max_readahead = 0;
+ 	}
+@@ -1928,10 +1936,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+ 			bufsize);
+ 		bufsize = FUSE_MIN_READ_BUFFER;
+ 	}
++	se->bufsize = bufsize;
+ 
+-	bufsize -= 4096;
+-	if (bufsize < se->conn.max_write)
+-		se->conn.max_write = 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)
+@@ -1958,6 +1966,14 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+ 		return;
+ 	}
+ 
++	if (se->conn.max_write < bufsize - FUSE_BUFFER_HEADER_SIZE) {
++		se->bufsize = se->conn.max_write + FUSE_BUFFER_HEADER_SIZE;
++	}
++	if (arg->flags & FUSE_MAX_PAGES) {
++		outarg.flags |= FUSE_MAX_PAGES;
++		outarg.max_pages = (se->conn.max_write - 1) / getpagesize() + 1;
++	}
++
+ 	/* Always enable big writes, this is superseded
+ 	   by the max_write option */
+ 	outarg.flags |= FUSE_BIG_WRITES;
+@@ -2779,11 +2795,6 @@ restart:
+ 	return res;
+ }
+ 
+-#define KERNEL_BUF_PAGES 32
+-
+-/* room needed in buffer to accommodate header */
+-#define HEADER_SIZE 0x1000
+-
+ struct fuse_session *fuse_session_new(struct fuse_args *args,
+ 				      const struct fuse_lowlevel_ops *op,
+ 				      size_t op_size, void *userdata)
+@@ -2844,7 +2855,8 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
+ 	if (se->debug)
+ 		fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
+ 
+-	se->bufsize = KERNEL_BUF_PAGES * getpagesize() + HEADER_SIZE;
++	se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() +
++		FUSE_BUFFER_HEADER_SIZE;
+ 
+ 	list_init_req(&se->list);
+ 	list_init_req(&se->interrupts);
+-- 
+2.36.1
+
diff --git a/SOURCES/0003-Allow-caching-symlinks-in-kernel-page-cache.-551.patch b/SOURCES/0003-Allow-caching-symlinks-in-kernel-page-cache.-551.patch
new file mode 100644
index 0000000..4e0e79c
--- /dev/null
+++ b/SOURCES/0003-Allow-caching-symlinks-in-kernel-page-cache.-551.patch
@@ -0,0 +1,83 @@
+From be7f19b21c84004c5a0705f040b957fd1c609e2e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Etienne=20Dubl=C3=A9?= <etienne.duble@imag.fr>
+Date: Sun, 20 Sep 2020 20:08:15 +0200
+Subject: [PATCH 3/4] Allow caching symlinks in kernel page cache. (#551)
+
+This commit defines a new capability called `FUSE_CAP_CACHE_SYMLINKS`.
+It is off by default but you can now enable it by setting this flag in
+in the `want` field of the `fuse_conn_info` structure.
+
+When enabled, the kernel will save symlinks in its page cache,
+by making use of the feature introduced in kernel 4.20:
+https://github.com/torvalds/linux/commit/5571f1e65486be025f73fa6aa30fb03725d362a2
+
+(cherry picked from commit ba3b225a126ebb3c6d4fe27c9f7c73aa4167001e)
+Signed-off-by: Pavel Reichl <preichl@redhat.com>
+---
+ example/printcap.c    |  2 ++
+ include/fuse_common.h | 13 +++++++++++++
+ lib/fuse_lowlevel.c   |  4 ++++
+ 3 files changed, 19 insertions(+)
+
+diff --git a/example/printcap.c b/example/printcap.c
+index 77dea14..a66036f 100644
+--- a/example/printcap.c
++++ b/example/printcap.c
+@@ -77,6 +77,8 @@ static void pc_init(void *userdata,
+ 			printf("\tFUSE_CAP_PARALLEL_DIROPS\n");
+ 	if(conn->capable & FUSE_CAP_POSIX_ACL)
+ 			printf("\tFUSE_CAP_POSIX_ACL\n");
++	if(conn->capable & FUSE_CAP_CACHE_SYMLINKS)
++			printf("\tFUSE_CAP_CACHE_SYMLINKS\n");
+ 	fuse_session_exit(se);
+ }
+ 
+diff --git a/include/fuse_common.h b/include/fuse_common.h
+index 83c9dee..a5a0ea5 100644
+--- a/include/fuse_common.h
++++ b/include/fuse_common.h
+@@ -316,6 +316,19 @@ struct fuse_loop_config {
+  */
+ #define FUSE_CAP_HANDLE_KILLPRIV         (1 << 20)
+ 
++/**
++ * Indicates that the kernel supports caching symlinks in its page cache.
++ *
++ * When this feature is enabled, symlink targets are saved in the page cache.
++ * You can invalidate a cached link by calling:
++ * `fuse_lowlevel_notify_inval_inode(se, ino, 0, 0);`
++ *
++ * This feature is disabled by default.
++ * If the kernel supports it (>= 4.20), you can enable this feature by
++ * setting this flag in the `want` field of the `fuse_conn_info` structure.
++ */
++#define FUSE_CAP_CACHE_SYMLINKS        (1 << 23)
++
+ /**
+  * Ioctl flags
+  *
+diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
+index 60195e0..43f785f 100644
+--- a/lib/fuse_lowlevel.c
++++ b/lib/fuse_lowlevel.c
+@@ -1882,6 +1882,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+ 			se->conn.capable |= FUSE_CAP_POSIX_ACL;
+ 		if (arg->flags & FUSE_HANDLE_KILLPRIV)
+ 			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
++		if (arg->flags & FUSE_CACHE_SYMLINKS)
++			se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS;
+ 		if (!(arg->flags & FUSE_MAX_PAGES)) {
+ 			size_t max_bufsize =
+ 				FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize()
+@@ -2002,6 +2004,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+ 		outarg.flags |= FUSE_WRITEBACK_CACHE;
+ 	if (se->conn.want & FUSE_CAP_POSIX_ACL)
+ 		outarg.flags |= FUSE_POSIX_ACL;
++	if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
++		outarg.flags |= FUSE_CACHE_SYMLINKS;
+ 	outarg.max_readahead = se->conn.max_readahead;
+ 	outarg.max_write = se->conn.max_write;
+ 	if (se->conn.proto_minor >= 13) {
+-- 
+2.36.1
+
diff --git a/SOURCES/0004-Add-support-for-in-kernel-readdir-caching.patch b/SOURCES/0004-Add-support-for-in-kernel-readdir-caching.patch
new file mode 100644
index 0000000..29bcb9c
--- /dev/null
+++ b/SOURCES/0004-Add-support-for-in-kernel-readdir-caching.patch
@@ -0,0 +1,65 @@
+From da57354dc8593d37eff59bc7836ee4e460a2659a Mon Sep 17 00:00:00 2001
+From: Nikolaus Rath <Nikolaus@rath.org>
+Date: Sat, 6 Apr 2019 18:34:57 +0100
+Subject: [PATCH 4/4] Add support for in-kernel readdir caching.
+
+Fixes: #394.
+(cherry picked from commit 1552b467fcd7751360299c5139382d78538e12b3)
+Signed-off-by: Pavel Reichl <preichl@redhat.com>
+---
+ include/fuse_common.h | 18 +++++++++++++-----
+ lib/fuse_lowlevel.c   |  2 ++
+ 2 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/include/fuse_common.h b/include/fuse_common.h
+index a5a0ea5..a28ffa5 100644
+--- a/include/fuse_common.h
++++ b/include/fuse_common.h
+@@ -45,9 +45,11 @@ struct fuse_file_info {
+ 	/** 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, to indicate that currently
+-	    cached file data (that the filesystem provided the last
+-	    time the file was open) need not be invalidated. */
++	/** 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;
+ 
+ 	/** Indicates a flush operation.  Set in flush operation, also
+@@ -64,8 +66,14 @@ struct fuse_file_info {
+ 	   May only be set in ->release(). */
+ 	unsigned int flock_release : 1;
+ 
+-	/** Padding.  Do not use*/
+-	unsigned int padding : 27;
++	/** Can be filled in by opendir. It signals the kernel to
++	    enable caching of entries returned by readdir().  Has no
++	    effect when set in other contexts (in particular it does
++	    nothing when set by open()). */
++	unsigned int cache_readdir : 1;
++
++	/** Padding.  Reserved for future use*/
++	unsigned int padding : 26;
+ 
+ 	/** File handle.  May be filled in by filesystem in open().
+ 	    Available in all other file operations */
+diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
+index 43f785f..6379e09 100644
+--- a/lib/fuse_lowlevel.c
++++ b/lib/fuse_lowlevel.c
+@@ -392,6 +392,8 @@ static void fill_open(struct fuse_open_out *arg,
+ 		arg->open_flags |= FOPEN_DIRECT_IO;
+ 	if (f->keep_cache)
+ 		arg->open_flags |= FOPEN_KEEP_CACHE;
++	if (f->cache_readdir)
++		arg->open_flags |= FOPEN_CACHE_DIR;
+ 	if (f->nonseekable)
+ 		arg->open_flags |= FOPEN_NONSEEKABLE;
+ }
+-- 
+2.36.1
+
diff --git a/SPECS/fuse.spec b/SPECS/fuse.spec
index fc7fed9..4d1f0a6 100644
--- a/SPECS/fuse.spec
+++ b/SPECS/fuse.spec
@@ -4,7 +4,7 @@
 
 Name:		fuse
 Version:	%{fuse2ver}
-Release:	15%{?dist}
+Release:	16%{?dist}
 Summary:	File System in Userspace (FUSE) v2 utilities
 License:	GPL+
 URL:		http://fuse.sf.net
@@ -22,6 +22,10 @@ Patch4:		fuse-3.2.1-no-dev.patch
 Patch5:		fusermount-don-t-feed-escaped-commas-into-mount-opti.patch
 Patch6:		buffer_size.patch
 Patch7:		fuse-3.10.4-fix-test-failure.patch
+Patch8:		0001-Synchronize-fuse_kernel.h.patch
+Patch9:		0002-fuse_lowlevel-Add-max_pages-support-384.patch
+Patch10:	0003-Allow-caching-symlinks-in-kernel-page-cache.-551.patch
+Patch11:	0004-Add-support-for-in-kernel-readdir-caching.patch
 
 Requires:	which
 Conflicts:	filesystem < 3
@@ -112,6 +116,11 @@ pushd lib%{name}-%{name}-%{fuse3ver}
 %patch1 -p1 -b .add_parentheses
 %patch4 -p1 -b .nodev
 %patch7 -p1 -b .test_fail
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+
 popd
 
 # fuse 2
@@ -242,6 +251,12 @@ rm -f %{buildroot}/usr/lib/udev/rules.d/99-fuse3.rules
 %{_includedir}/fuse3/
 
 %changelog
+* Mon May 30 2022 Pavel Reichl <preichl@redhat.com> - 2.9.7-16
+- Back-port max_pages support,
+- caching symlinks in kernel page cache,
+- and in-kernel readdir caching
+- Fixed rhbz#2080000
+
 * Wed Feb 23 2022 Pavel Reichl <preichl@redhat.com> - 2.9.7-15
 - Fix missing dependency of fuse3 on fuse3-libs
 - Make symlink for mount.fuse to mount.fuse3