--- /dev/null
+From 0f5da9dac07c4bf3add7da401bbe39893143480f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Oct 2021 08:25:25 +0200
+Subject: block: remove __sync_blockdev
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 70164eb6ccb76ab679b016b4b60123bf4ec6c162 ]
+
+Instead offer a new sync_blockdev_nowait helper for the !wait case.
+This new helper is exported as it will grow modular callers in a bit.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20211019062530.2174626-3-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/bdev.c | 11 ++++++-----
+ fs/internal.h | 5 -----
+ fs/sync.c | 7 ++++---
+ include/linux/blkdev.h | 5 +++++
+ 4 files changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 485a258b0ab3..33cac289302e 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -184,14 +184,13 @@ int sb_min_blocksize(struct super_block *sb, int size)
+
+ EXPORT_SYMBOL(sb_min_blocksize);
+
+-int __sync_blockdev(struct block_device *bdev, int wait)
++int sync_blockdev_nowait(struct block_device *bdev)
+ {
+ if (!bdev)
+ return 0;
+- if (!wait)
+- return filemap_flush(bdev->bd_inode->i_mapping);
+- return filemap_write_and_wait(bdev->bd_inode->i_mapping);
++ return filemap_flush(bdev->bd_inode->i_mapping);
+ }
++EXPORT_SYMBOL_GPL(sync_blockdev_nowait);
+
+ /*
+ * Write out and wait upon all the dirty data associated with a block
+@@ -199,7 +198,9 @@ int __sync_blockdev(struct block_device *bdev, int wait)
+ */
+ int sync_blockdev(struct block_device *bdev)
+ {
+- return __sync_blockdev(bdev, 1);
++ if (!bdev)
++ return 0;
++ return filemap_write_and_wait(bdev->bd_inode->i_mapping);
+ }
+ EXPORT_SYMBOL(sync_blockdev);
+
+diff --git a/fs/internal.h b/fs/internal.h
+index 3cd065c8a66b..b5caa16f4645 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -23,7 +23,6 @@ struct pipe_inode_info;
+ #ifdef CONFIG_BLOCK
+ extern void __init bdev_cache_init(void);
+
+-extern int __sync_blockdev(struct block_device *bdev, int wait);
+ void iterate_bdevs(void (*)(struct block_device *, void *), void *);
+ void emergency_thaw_bdev(struct super_block *sb);
+ #else
+@@ -31,10 +30,6 @@ static inline void bdev_cache_init(void)
+ {
+ }
+
+-static inline int __sync_blockdev(struct block_device *bdev, int wait)
+-{
+- return 0;
+-}
+ static inline void iterate_bdevs(void (*f)(struct block_device *, void *),
+ void *arg)
+ {
+diff --git a/fs/sync.c b/fs/sync.c
+index 0d6cdc507cb9..a621089eb07e 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -3,6 +3,7 @@
+ * High-level sync()-related operations
+ */
+
++#include <linux/blkdev.h>
+ #include <linux/kernel.h>
+ #include <linux/file.h>
+ #include <linux/fs.h>
+@@ -45,7 +46,7 @@ int sync_filesystem(struct super_block *sb)
+ /*
+ * Do the filesystem syncing work. For simple filesystems
+ * writeback_inodes_sb(sb) just dirties buffers with inodes so we have
+- * to submit I/O for these buffers via __sync_blockdev(). This also
++ * to submit I/O for these buffers via sync_blockdev(). This also
+ * speeds up the wait == 1 case since in that case write_inode()
+ * methods call sync_dirty_buffer() and thus effectively write one block
+ * at a time.
+@@ -53,14 +54,14 @@ int sync_filesystem(struct super_block *sb)
+ writeback_inodes_sb(sb, WB_REASON_SYNC);
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, 0);
+- ret = __sync_blockdev(sb->s_bdev, 0);
++ ret = sync_blockdev_nowait(sb->s_bdev);
+ if (ret < 0)
+ return ret;
+
+ sync_inodes_sb(sb);
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, 1);
+- return __sync_blockdev(sb->s_bdev, 1);
++ return sync_blockdev(sb->s_bdev);
+ }
+ EXPORT_SYMBOL(sync_filesystem);
+
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 413c0148c0ce..6bbd393e6bcc 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -1999,6 +1999,7 @@ int truncate_bdev_range(struct block_device *bdev, fmode_t mode, loff_t lstart,
+ #ifdef CONFIG_BLOCK
+ void invalidate_bdev(struct block_device *bdev);
+ int sync_blockdev(struct block_device *bdev);
++int sync_blockdev_nowait(struct block_device *bdev);
+ #else
+ static inline void invalidate_bdev(struct block_device *bdev)
+ {
+@@ -2007,6 +2008,10 @@ static inline int sync_blockdev(struct block_device *bdev)
+ {
+ return 0;
+ }
++static inline int sync_blockdev_nowait(struct block_device *bdev)
++{
++ return 0;
++}
+ #endif
+ int fsync_bdev(struct block_device *bdev);
+
+--
+2.35.1
+
--- /dev/null
+From 22110c694ece8b06a1f0625f9b1b5656726005f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Oct 2021 08:25:30 +0200
+Subject: block: simplify the block device syncing code
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 1e03a36bdff4709c1bbf0f57f60ae3f776d51adf ]
+
+Get rid of the indirections and just provide a sync_bdevs
+helper for the generic sync code.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20211019062530.2174626-8-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/bdev.c | 17 ++++++++++++++---
+ fs/internal.h | 6 ------
+ fs/sync.c | 23 ++++-------------------
+ include/linux/blkdev.h | 4 ++++
+ 4 files changed, 22 insertions(+), 28 deletions(-)
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 33cac289302e..18abafb135e0 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -1017,7 +1017,7 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty)
+ }
+ EXPORT_SYMBOL(__invalidate_device);
+
+-void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
++void sync_bdevs(bool wait)
+ {
+ struct inode *inode, *old_inode = NULL;
+
+@@ -1048,8 +1048,19 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
+ bdev = I_BDEV(inode);
+
+ mutex_lock(&bdev->bd_disk->open_mutex);
+- if (bdev->bd_openers)
+- func(bdev, arg);
++ if (!bdev->bd_openers) {
++ ; /* skip */
++ } else if (wait) {
++ /*
++ * We keep the error status of individual mapping so
++ * that applications can catch the writeback error using
++ * fsync(2). See filemap_fdatawait_keep_errors() for
++ * details.
++ */
++ filemap_fdatawait_keep_errors(inode->i_mapping);
++ } else {
++ filemap_fdatawrite(inode->i_mapping);
++ }
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+
+ spin_lock(&blockdev_superblock->s_inode_list_lock);
+diff --git a/fs/internal.h b/fs/internal.h
+index b5caa16f4645..cdd83d4899bb 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -23,17 +23,11 @@ struct pipe_inode_info;
+ #ifdef CONFIG_BLOCK
+ extern void __init bdev_cache_init(void);
+
+-void iterate_bdevs(void (*)(struct block_device *, void *), void *);
+ void emergency_thaw_bdev(struct super_block *sb);
+ #else
+ static inline void bdev_cache_init(void)
+ {
+ }
+-
+-static inline void iterate_bdevs(void (*f)(struct block_device *, void *),
+- void *arg)
+-{
+-}
+ static inline int emergency_thaw_bdev(struct super_block *sb)
+ {
+ return 0;
+diff --git a/fs/sync.c b/fs/sync.c
+index a621089eb07e..3ce8e2137f31 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -78,21 +78,6 @@ static void sync_fs_one_sb(struct super_block *sb, void *arg)
+ sb->s_op->sync_fs(sb, *(int *)arg);
+ }
+
+-static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
+-{
+- filemap_fdatawrite(bdev->bd_inode->i_mapping);
+-}
+-
+-static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
+-{
+- /*
+- * We keep the error status of individual mapping so that
+- * applications can catch the writeback error using fsync(2).
+- * See filemap_fdatawait_keep_errors() for details.
+- */
+- filemap_fdatawait_keep_errors(bdev->bd_inode->i_mapping);
+-}
+-
+ /*
+ * Sync everything. We start by waking flusher threads so that most of
+ * writeback runs on all devices in parallel. Then we sync all inodes reliably
+@@ -111,8 +96,8 @@ void ksys_sync(void)
+ iterate_supers(sync_inodes_one_sb, NULL);
+ iterate_supers(sync_fs_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &wait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
+- iterate_bdevs(fdatawait_one_bdev, NULL);
++ sync_bdevs(false);
++ sync_bdevs(true);
+ if (unlikely(laptop_mode))
+ laptop_sync_completion();
+ }
+@@ -133,10 +118,10 @@ static void do_sync_work(struct work_struct *work)
+ */
+ iterate_supers(sync_inodes_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &nowait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
++ sync_bdevs(false);
+ iterate_supers(sync_inodes_one_sb, &nowait);
+ iterate_supers(sync_fs_one_sb, &nowait);
+- iterate_bdevs(fdatawrite_one_bdev, NULL);
++ sync_bdevs(false);
+ printk("Emergency Sync complete\n");
+ kfree(work);
+ }
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 6bbd393e6bcc..aebe67ed7a73 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -2000,6 +2000,7 @@ int truncate_bdev_range(struct block_device *bdev, fmode_t mode, loff_t lstart,
+ void invalidate_bdev(struct block_device *bdev);
+ int sync_blockdev(struct block_device *bdev);
+ int sync_blockdev_nowait(struct block_device *bdev);
++void sync_bdevs(bool wait);
+ #else
+ static inline void invalidate_bdev(struct block_device *bdev)
+ {
+@@ -2012,6 +2013,9 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
+ {
+ return 0;
+ }
++static inline void sync_bdevs(bool wait)
++{
++}
+ #endif
+ int fsync_bdev(struct block_device *bdev);
+
+--
+2.35.1
+
--- /dev/null
+From 7370977fefdc738478af84515fdc1dcdc44f201e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Oct 2021 08:25:24 +0200
+Subject: fs: remove __sync_filesystem
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 9a208ba5c9afa62c7b1e9c6f5e783066e84e2d3c ]
+
+There is no clear benefit in having this helper vs just open coding it.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Link: https://lore.kernel.org/r/20211019062530.2174626-2-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/sync.c | 38 +++++++++++++++++---------------------
+ 1 file changed, 17 insertions(+), 21 deletions(-)
+
+diff --git a/fs/sync.c b/fs/sync.c
+index 1373a610dc78..0d6cdc507cb9 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -21,25 +21,6 @@
+ #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
+ SYNC_FILE_RANGE_WAIT_AFTER)
+
+-/*
+- * Do the filesystem syncing work. For simple filesystems
+- * writeback_inodes_sb(sb) just dirties buffers with inodes so we have to
+- * submit IO for these buffers via __sync_blockdev(). This also speeds up the
+- * wait == 1 case since in that case write_inode() functions do
+- * sync_dirty_buffer() and thus effectively write one block at a time.
+- */
+-static int __sync_filesystem(struct super_block *sb, int wait)
+-{
+- if (wait)
+- sync_inodes_sb(sb);
+- else
+- writeback_inodes_sb(sb, WB_REASON_SYNC);
+-
+- if (sb->s_op->sync_fs)
+- sb->s_op->sync_fs(sb, wait);
+- return __sync_blockdev(sb->s_bdev, wait);
+-}
+-
+ /*
+ * Write out and wait upon all dirty data associated with this
+ * superblock. Filesystem data as well as the underlying block
+@@ -61,10 +42,25 @@ int sync_filesystem(struct super_block *sb)
+ if (sb_rdonly(sb))
+ return 0;
+
+- ret = __sync_filesystem(sb, 0);
++ /*
++ * Do the filesystem syncing work. For simple filesystems
++ * writeback_inodes_sb(sb) just dirties buffers with inodes so we have
++ * to submit I/O for these buffers via __sync_blockdev(). This also
++ * speeds up the wait == 1 case since in that case write_inode()
++ * methods call sync_dirty_buffer() and thus effectively write one block
++ * at a time.
++ */
++ writeback_inodes_sb(sb, WB_REASON_SYNC);
++ if (sb->s_op->sync_fs)
++ sb->s_op->sync_fs(sb, 0);
++ ret = __sync_blockdev(sb->s_bdev, 0);
+ if (ret < 0)
+ return ret;
+- return __sync_filesystem(sb, 1);
++
++ sync_inodes_sb(sb);
++ if (sb->s_op->sync_fs)
++ sb->s_op->sync_fs(sb, 1);
++ return __sync_blockdev(sb->s_bdev, 1);
+ }
+ EXPORT_SYMBOL(sync_filesystem);
+
+--
+2.35.1
+
--- /dev/null
+fs-remove-__sync_filesystem.patch
+block-remove-__sync_blockdev.patch
+block-simplify-the-block-device-syncing-code.patch
+vfs-make-sync_filesystem-return-errors-from-sync_fs.patch
+xfs-return-errors-in-xfs_fs_sync_fs.patch
--- /dev/null
+From 81a1f9ff222929053aa8dda60021a5350e667da4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 30 Jan 2022 08:53:16 -0800
+Subject: vfs: make sync_filesystem return errors from ->sync_fs
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+[ Upstream commit 5679897eb104cec9e99609c3f045a0c20603da4c ]
+
+Strangely, sync_filesystem ignores the return code from the ->sync_fs
+call, which means that syscalls like syncfs(2) never see the error.
+This doesn't seem right, so fix that.
+
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/sync.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/fs/sync.c b/fs/sync.c
+index 3ce8e2137f31..c7690016453e 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -29,7 +29,7 @@
+ */
+ int sync_filesystem(struct super_block *sb)
+ {
+- int ret;
++ int ret = 0;
+
+ /*
+ * We need to be protected against the filesystem going from
+@@ -52,15 +52,21 @@ int sync_filesystem(struct super_block *sb)
+ * at a time.
+ */
+ writeback_inodes_sb(sb, WB_REASON_SYNC);
+- if (sb->s_op->sync_fs)
+- sb->s_op->sync_fs(sb, 0);
++ if (sb->s_op->sync_fs) {
++ ret = sb->s_op->sync_fs(sb, 0);
++ if (ret)
++ return ret;
++ }
+ ret = sync_blockdev_nowait(sb->s_bdev);
+- if (ret < 0)
++ if (ret)
+ return ret;
+
+ sync_inodes_sb(sb);
+- if (sb->s_op->sync_fs)
+- sb->s_op->sync_fs(sb, 1);
++ if (sb->s_op->sync_fs) {
++ ret = sb->s_op->sync_fs(sb, 1);
++ if (ret)
++ return ret;
++ }
+ return sync_blockdev(sb->s_bdev);
+ }
+ EXPORT_SYMBOL(sync_filesystem);
+--
+2.35.1
+
--- /dev/null
+From 1325aa6868b83e6ae24efc43f0897f0faf50389d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 30 Jan 2022 08:53:17 -0800
+Subject: xfs: return errors in xfs_fs_sync_fs
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+[ Upstream commit 2d86293c70750e4331e9616aded33ab6b47c299d ]
+
+Now that the VFS will do something with the return values from
+->sync_fs, make ours pass on error codes.
+
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_super.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
+index c4e0cd1c1c8c..170fee98c45c 100644
+--- a/fs/xfs/xfs_super.c
++++ b/fs/xfs/xfs_super.c
+@@ -729,6 +729,7 @@ xfs_fs_sync_fs(
+ int wait)
+ {
+ struct xfs_mount *mp = XFS_M(sb);
++ int error;
+
+ trace_xfs_fs_sync_fs(mp, __return_address);
+
+@@ -738,7 +739,10 @@ xfs_fs_sync_fs(
+ if (!wait)
+ return 0;
+
+- xfs_log_force(mp, XFS_LOG_SYNC);
++ error = xfs_log_force(mp, XFS_LOG_SYNC);
++ if (error)
++ return error;
++
+ if (laptop_mode) {
+ /*
+ * The disk must be active because we're syncing.
+--
+2.35.1
+