--- /dev/null
+From ccc031e26afe60d2a5a3d93dabd9c978210825fb Mon Sep 17 00:00:00 2001
+From: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
+Date: Wed, 28 Sep 2022 20:19:34 +0800
+Subject: fuse: always revalidate rename target dentry
+
+From: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
+
+commit ccc031e26afe60d2a5a3d93dabd9c978210825fb upstream.
+
+The previous commit df8629af2934 ("fuse: always revalidate if exclusive
+create") ensures that the dentries are revalidated on O_EXCL creates. This
+commit complements it by also performing revalidation for rename target
+dentries. Otherwise, a rename target file that only exists in kernel
+dentry cache but not in the filesystem will result in EEXIST if
+RENAME_NOREPLACE flag is used.
+
+Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
+Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Yang Bo <yb203166@antfin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dir.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -205,7 +205,7 @@ static int fuse_dentry_revalidate(struct
+ if (inode && fuse_is_bad(inode))
+ goto invalid;
+ else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
+- (flags & (LOOKUP_EXCL | LOOKUP_REVAL))) {
++ (flags & (LOOKUP_EXCL | LOOKUP_REVAL | LOOKUP_RENAME_TARGET))) {
+ struct fuse_entry_out outarg;
+ FUSE_ARGS(args);
+ struct fuse_forget_link *forget;
--- /dev/null
+From 484ce65715b06aead8c4901f01ca32c5a240bc71 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Fri, 22 Oct 2021 17:03:03 +0200
+Subject: fuse: fix attr version comparison in fuse_read_update_size()
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit 484ce65715b06aead8c4901f01ca32c5a240bc71 upstream.
+
+A READ request returning a short count is taken as indication of EOF, and
+the cached file size is modified accordingly.
+
+Fix the attribute version checking to allow for changes to fc->attr_version
+on other inodes.
+
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Yang Bo <yb203166@antfin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/file.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -793,7 +793,7 @@ static void fuse_read_update_size(struct
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
+ spin_lock(&fi->lock);
+- if (attr_ver == fi->attr_version && size < inode->i_size &&
++ if (attr_ver >= fi->attr_version && size < inode->i_size &&
+ !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
+ fi->attr_version = atomic64_inc_return(&fc->attr_version);
+ i_size_write(inode, size);
--- /dev/null
+From 2fdbb8dd01556e1501132b5ad3826e8f71e24a8b Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Fri, 22 Apr 2022 15:48:53 +0200
+Subject: fuse: fix deadlock between atomic O_TRUNC and page invalidation
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit 2fdbb8dd01556e1501132b5ad3826e8f71e24a8b upstream.
+
+fuse_finish_open() will be called with FUSE_NOWRITE set in case of atomic
+O_TRUNC open(), so commit 76224355db75 ("fuse: truncate pagecache on
+atomic_o_trunc") replaced invalidate_inode_pages2() by truncate_pagecache()
+in such a case to avoid the A-A deadlock. However, we found another A-B-B-A
+deadlock related to the case above, which will cause the xfstests
+generic/464 testcase hung in our virtio-fs test environment.
+
+For example, consider two processes concurrently open one same file, one
+with O_TRUNC and another without O_TRUNC. The deadlock case is described
+below, if open(O_TRUNC) is already set_nowrite(acquired A), and is trying
+to lock a page (acquiring B), open() could have held the page lock
+(acquired B), and waiting on the page writeback (acquiring A). This would
+lead to deadlocks.
+
+open(O_TRUNC)
+----------------------------------------------------------------
+fuse_open_common
+ inode_lock [C acquire]
+ fuse_set_nowrite [A acquire]
+
+ fuse_finish_open
+ truncate_pagecache
+ lock_page [B acquire]
+ truncate_inode_page
+ unlock_page [B release]
+
+ fuse_release_nowrite [A release]
+ inode_unlock [C release]
+----------------------------------------------------------------
+
+open()
+----------------------------------------------------------------
+fuse_open_common
+ fuse_finish_open
+ invalidate_inode_pages2
+ lock_page [B acquire]
+ fuse_launder_page
+ fuse_wait_on_page_writeback [A acquire & release]
+ unlock_page [B release]
+----------------------------------------------------------------
+
+Besides this case, all calls of invalidate_inode_pages2() and
+invalidate_inode_pages2_range() in fuse code also can deadlock with
+open(O_TRUNC).
+
+Fix by moving the truncate_pagecache() call outside the nowrite protected
+region. The nowrite protection is only for delayed writeback
+(writeback_cache) case, where inode lock does not protect against
+truncation racing with writes on the server. Write syscalls racing with
+page cache truncation still get the inode lock protection.
+
+This patch also changes the order of filemap_invalidate_lock()
+vs. fuse_set_nowrite() in fuse_open_common(). This new order matches the
+order found in fuse_file_fallocate() and fuse_do_setattr().
+
+Reported-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
+Tested-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
+Fixes: e4648309b85a ("fuse: truncate pending writes on O_TRUNC")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Yang Bo <yb203166@antfin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dir.c | 7 ++++++-
+ fs/fuse/file.c | 29 +++++++++++++++++------------
+ 2 files changed, 23 insertions(+), 13 deletions(-)
+
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -476,6 +476,7 @@ static int fuse_create_open(struct inode
+ struct fuse_entry_out outentry;
+ struct fuse_inode *fi;
+ struct fuse_file *ff;
++ bool trunc = flags & O_TRUNC;
+
+ /* Userspace expects S_IFREG in create mode */
+ BUG_ON((mode & S_IFMT) != S_IFREG);
+@@ -500,7 +501,7 @@ static int fuse_create_open(struct inode
+ inarg.mode = mode;
+ inarg.umask = current_umask();
+
+- if (fm->fc->handle_killpriv_v2 && (flags & O_TRUNC) &&
++ if (fm->fc->handle_killpriv_v2 && trunc &&
+ !(flags & O_EXCL) && !capable(CAP_FSETID)) {
+ inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
+ }
+@@ -549,6 +550,10 @@ static int fuse_create_open(struct inode
+ } else {
+ file->private_data = ff;
+ fuse_finish_open(inode, file);
++ if (fm->fc->atomic_o_trunc && trunc)
++ truncate_pagecache(inode, 0);
++ else if (!(ff->open_flags & FOPEN_KEEP_CACHE))
++ invalidate_inode_pages2(inode->i_mapping);
+ }
+ return err;
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -210,12 +210,9 @@ void fuse_finish_open(struct inode *inod
+ fi->attr_version = atomic64_inc_return(&fc->attr_version);
+ i_size_write(inode, 0);
+ spin_unlock(&fi->lock);
+- truncate_pagecache(inode, 0);
+ fuse_invalidate_attr(inode);
+ if (fc->writeback_cache)
+ file_update_time(file);
+- } else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) {
+- invalidate_inode_pages2(inode->i_mapping);
+ }
+
+ if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
+@@ -240,30 +237,38 @@ int fuse_open_common(struct inode *inode
+ if (err)
+ return err;
+
+- if (is_wb_truncate || dax_truncate) {
++ if (is_wb_truncate || dax_truncate)
+ inode_lock(inode);
+- fuse_set_nowrite(inode);
+- }
+
+ if (dax_truncate) {
+ filemap_invalidate_lock(inode->i_mapping);
+ err = fuse_dax_break_layouts(inode, 0, 0);
+ if (err)
+- goto out;
++ goto out_inode_unlock;
+ }
+
++ if (is_wb_truncate || dax_truncate)
++ fuse_set_nowrite(inode);
++
+ err = fuse_do_open(fm, get_node_id(inode), file, isdir);
+ if (!err)
+ fuse_finish_open(inode, file);
+
+-out:
++ if (is_wb_truncate || dax_truncate)
++ fuse_release_nowrite(inode);
++ if (!err) {
++ struct fuse_file *ff = file->private_data;
++
++ if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC))
++ truncate_pagecache(inode, 0);
++ else if (!(ff->open_flags & FOPEN_KEEP_CACHE))
++ invalidate_inode_pages2(inode->i_mapping);
++ }
+ if (dax_truncate)
+ filemap_invalidate_unlock(inode->i_mapping);
+-
+- if (is_wb_truncate | dax_truncate) {
+- fuse_release_nowrite(inode);
++out_inode_unlock:
++ if (is_wb_truncate || dax_truncate)
+ inode_unlock(inode);
+- }
+
+ return err;
+ }
--- /dev/null
+From d83806c4c0cccc0d6d3c3581a11983a9c186a138 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 26 Mar 2023 18:21:21 +0000
+Subject: purgatory: fix disabling debug info
+
+From: Alyssa Ross <hi@alyssa.is>
+
+commit d83806c4c0cccc0d6d3c3581a11983a9c186a138 upstream.
+
+Since 32ef9e5054ec, -Wa,-gdwarf-2 is no longer used in KBUILD_AFLAGS.
+Instead, it includes -g, the appropriate -gdwarf-* flag, and also the
+-Wa versions of both of those if building with Clang and GNU as. As a
+result, debug info was being generated for the purgatory objects, even
+though the intention was that it not be.
+
+Fixes: 32ef9e5054ec ("Makefile.debug: re-enable debug info for .S files")
+Signed-off-by: Alyssa Ross <hi@alyssa.is>
+Cc: stable@vger.kernel.org
+Acked-by: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/purgatory/Makefile | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -64,8 +64,7 @@ CFLAGS_sha256.o += $(PURGATORY_CFLAGS)
+ CFLAGS_REMOVE_string.o += $(PURGATORY_CFLAGS_REMOVE)
+ CFLAGS_string.o += $(PURGATORY_CFLAGS)
+
+-AFLAGS_REMOVE_setup-x86_$(BITS).o += -Wa,-gdwarf-2
+-AFLAGS_REMOVE_entry64.o += -Wa,-gdwarf-2
++asflags-remove-y += -g -Wa,-gdwarf-2
+
+ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
+ $(call if_changed,ld)