+++ /dev/null
-From 84133ca398f3d3a0563b2b47a0c0d86191848b2b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 13 Oct 2023 14:13:50 +0200
-Subject: ext4: properly sync file size update after O_SYNC direct IO
-
-From: Jan Kara <jack@suse.cz>
-
-[ Upstream commit 91562895f8030cb9a0470b1db49de79346a69f91 ]
-
-Gao Xiang has reported that on ext4 O_SYNC direct IO does not properly
-sync file size update and thus if we crash at unfortunate moment, the
-file can have smaller size although O_SYNC IO has reported successful
-completion. The problem happens because update of on-disk inode size is
-handled in ext4_dio_write_iter() *after* iomap_dio_rw() (and thus
-dio_complete() in particular) has returned and generic_file_sync() gets
-called by dio_complete(). Fix the problem by handling on-disk inode size
-update directly in our ->end_io completion handler.
-
-References: https://lore.kernel.org/all/02d18236-26ef-09b0-90ad-030c4fe3ee20@linux.alibaba.com
-Reported-by: Gao Xiang <hsiangkao@linux.alibaba.com>
-CC: stable@vger.kernel.org
-Fixes: 378f32bab371 ("ext4: introduce direct I/O write using iomap infrastructure")
-Signed-off-by: Jan Kara <jack@suse.cz>
-Tested-by: Joseph Qi <joseph.qi@linux.alibaba.com>
-Reviewed-by: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
-Link: https://lore.kernel.org/r/20231013121350.26872-1-jack@suse.cz
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/file.c | 153 +++++++++++++++++++++----------------------------
- 1 file changed, 65 insertions(+), 88 deletions(-)
-
-diff --git a/fs/ext4/file.c b/fs/ext4/file.c
-index f42cc1fe0ba1d..15f45499f491a 100644
---- a/fs/ext4/file.c
-+++ b/fs/ext4/file.c
-@@ -280,80 +280,38 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,
- }
-
- static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
-- ssize_t written, size_t count)
-+ ssize_t count)
- {
- handle_t *handle;
-- bool truncate = false;
-- u8 blkbits = inode->i_blkbits;
-- ext4_lblk_t written_blk, end_blk;
-- int ret;
--
-- /*
-- * Note that EXT4_I(inode)->i_disksize can get extended up to
-- * inode->i_size while the I/O was running due to writeback of delalloc
-- * blocks. But, the code in ext4_iomap_alloc() is careful to use
-- * zeroed/unwritten extents if this is possible; thus we won't leave
-- * uninitialized blocks in a file even if we didn't succeed in writing
-- * as much as we intended.
-- */
-- WARN_ON_ONCE(i_size_read(inode) < EXT4_I(inode)->i_disksize);
-- if (offset + count <= EXT4_I(inode)->i_disksize) {
-- /*
-- * We need to ensure that the inode is removed from the orphan
-- * list if it has been added prematurely, due to writeback of
-- * delalloc blocks.
-- */
-- if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
-- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
--
-- if (IS_ERR(handle)) {
-- ext4_orphan_del(NULL, inode);
-- return PTR_ERR(handle);
-- }
--
-- ext4_orphan_del(handle, inode);
-- ext4_journal_stop(handle);
-- }
--
-- return written;
-- }
--
-- if (written < 0)
-- goto truncate;
-
-+ lockdep_assert_held_write(&inode->i_rwsem);
- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
-- if (IS_ERR(handle)) {
-- written = PTR_ERR(handle);
-- goto truncate;
-- }
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-
-- if (ext4_update_inode_size(inode, offset + written)) {
-- ret = ext4_mark_inode_dirty(handle, inode);
-+ if (ext4_update_inode_size(inode, offset + count)) {
-+ int ret = ext4_mark_inode_dirty(handle, inode);
- if (unlikely(ret)) {
-- written = ret;
- ext4_journal_stop(handle);
-- goto truncate;
-+ return ret;
- }
- }
-
-- /*
-- * We may need to truncate allocated but not written blocks beyond EOF.
-- */
-- written_blk = ALIGN(offset + written, 1 << blkbits);
-- end_blk = ALIGN(offset + count, 1 << blkbits);
-- if (written_blk < end_blk && ext4_can_truncate(inode))
-- truncate = true;
--
-- /*
-- * Remove the inode from the orphan list if it has been extended and
-- * everything went OK.
-- */
-- if (!truncate && inode->i_nlink)
-+ if (inode->i_nlink)
- ext4_orphan_del(handle, inode);
- ext4_journal_stop(handle);
-
-- if (truncate) {
--truncate:
-+ return count;
-+}
-+
-+/*
-+ * Clean up the inode after DIO or DAX extending write has completed and the
-+ * inode size has been updated using ext4_handle_inode_extension().
-+ */
-+static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
-+{
-+ lockdep_assert_held_write(&inode->i_rwsem);
-+ if (count < 0) {
- ext4_truncate_failed_write(inode);
- /*
- * If the truncate operation failed early, then the inode may
-@@ -362,9 +320,28 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
- */
- if (inode->i_nlink)
- ext4_orphan_del(NULL, inode);
-+ return;
- }
-+ /*
-+ * If i_disksize got extended due to writeback of delalloc blocks while
-+ * the DIO was running we could fail to cleanup the orphan list in
-+ * ext4_handle_inode_extension(). Do it now.
-+ */
-+ if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
-+ handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
-
-- return written;
-+ if (IS_ERR(handle)) {
-+ /*
-+ * The write has successfully completed. Not much to
-+ * do with the error here so just cleanup the orphan
-+ * list and hope for the best.
-+ */
-+ ext4_orphan_del(NULL, inode);
-+ return;
-+ }
-+ ext4_orphan_del(handle, inode);
-+ ext4_journal_stop(handle);
-+ }
- }
-
- static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
-@@ -373,31 +350,22 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
- loff_t pos = iocb->ki_pos;
- struct inode *inode = file_inode(iocb->ki_filp);
-
-+ if (!error && size && flags & IOMAP_DIO_UNWRITTEN)
-+ error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
- if (error)
- return error;
--
-- if (size && flags & IOMAP_DIO_UNWRITTEN) {
-- error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
-- if (error < 0)
-- return error;
-- }
- /*
-- * If we are extending the file, we have to update i_size here before
-- * page cache gets invalidated in iomap_dio_rw(). Otherwise racing
-- * buffered reads could zero out too much from page cache pages. Update
-- * of on-disk size will happen later in ext4_dio_write_iter() where
-- * we have enough information to also perform orphan list handling etc.
-- * Note that we perform all extending writes synchronously under
-- * i_rwsem held exclusively so i_size update is safe here in that case.
-- * If the write was not extending, we cannot see pos > i_size here
-- * because operations reducing i_size like truncate wait for all
-- * outstanding DIO before updating i_size.
-+ * Note that EXT4_I(inode)->i_disksize can get extended up to
-+ * inode->i_size while the I/O was running due to writeback of delalloc
-+ * blocks. But the code in ext4_iomap_alloc() is careful to use
-+ * zeroed/unwritten extents if this is possible; thus we won't leave
-+ * uninitialized blocks in a file even if we didn't succeed in writing
-+ * as much as we intended.
- */
-- pos += size;
-- if (pos > i_size_read(inode))
-- i_size_write(inode, pos);
--
-- return 0;
-+ WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize));
-+ if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize))
-+ return size;
-+ return ext4_handle_inode_extension(inode, pos, size);
- }
-
- static const struct iomap_dio_ops ext4_dio_write_ops = {
-@@ -572,9 +540,16 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
- is_sync_kiocb(iocb) || unaligned_io || extend);
- if (ret == -ENOTBLK)
- ret = 0;
--
-- if (extend)
-- ret = ext4_handle_inode_extension(inode, offset, ret, count);
-+ if (extend) {
-+ /*
-+ * We always perform extending DIO write synchronously so by
-+ * now the IO is completed and ext4_handle_inode_extension()
-+ * was called. Cleanup the inode in case of error or race with
-+ * writeback of delalloc blocks.
-+ */
-+ WARN_ON_ONCE(ret == -EIOCBQUEUED);
-+ ext4_inode_extension_cleanup(inode, ret);
-+ }
-
- out:
- if (ilock_shared)
-@@ -655,8 +630,10 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
-
- ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops);
-
-- if (extend)
-- ret = ext4_handle_inode_extension(inode, offset, ret, count);
-+ if (extend) {
-+ ret = ext4_handle_inode_extension(inode, offset, ret);
-+ ext4_inode_extension_cleanup(inode, ret);
-+ }
- out:
- inode_unlock(inode);
- if (ret > 0)
---
-2.42.0
-
misc-pci_endpoint_test-add-deviceid-for-j721s2-pcie-.patch
fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch
ima-annotate-iint-mutex-to-avoid-lockdep-false-posit.patch
-ext4-properly-sync-file-size-update-after-o_sync-dir.patch
driver-core-move-the-removable-attribute-from-usb-to.patch
drm-amdgpu-don-t-use-atrm-for-external-devices.patch
fs-add-ctime-accessors-infrastructure.patch
+++ /dev/null
-From 91d014706a567575472e4872abeac522965cbe1f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 13 Oct 2023 14:13:50 +0200
-Subject: ext4: properly sync file size update after O_SYNC direct IO
-
-From: Jan Kara <jack@suse.cz>
-
-[ Upstream commit 91562895f8030cb9a0470b1db49de79346a69f91 ]
-
-Gao Xiang has reported that on ext4 O_SYNC direct IO does not properly
-sync file size update and thus if we crash at unfortunate moment, the
-file can have smaller size although O_SYNC IO has reported successful
-completion. The problem happens because update of on-disk inode size is
-handled in ext4_dio_write_iter() *after* iomap_dio_rw() (and thus
-dio_complete() in particular) has returned and generic_file_sync() gets
-called by dio_complete(). Fix the problem by handling on-disk inode size
-update directly in our ->end_io completion handler.
-
-References: https://lore.kernel.org/all/02d18236-26ef-09b0-90ad-030c4fe3ee20@linux.alibaba.com
-Reported-by: Gao Xiang <hsiangkao@linux.alibaba.com>
-CC: stable@vger.kernel.org
-Fixes: 378f32bab371 ("ext4: introduce direct I/O write using iomap infrastructure")
-Signed-off-by: Jan Kara <jack@suse.cz>
-Tested-by: Joseph Qi <joseph.qi@linux.alibaba.com>
-Reviewed-by: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
-Link: https://lore.kernel.org/r/20231013121350.26872-1-jack@suse.cz
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/ext4/file.c | 153 +++++++++++++++++++++----------------------------
- 1 file changed, 65 insertions(+), 88 deletions(-)
-
-diff --git a/fs/ext4/file.c b/fs/ext4/file.c
-index 4704fe627c4e2..94ce73fadcba6 100644
---- a/fs/ext4/file.c
-+++ b/fs/ext4/file.c
-@@ -279,80 +279,38 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,
- }
-
- static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
-- ssize_t written, size_t count)
-+ ssize_t count)
- {
- handle_t *handle;
-- bool truncate = false;
-- u8 blkbits = inode->i_blkbits;
-- ext4_lblk_t written_blk, end_blk;
-- int ret;
--
-- /*
-- * Note that EXT4_I(inode)->i_disksize can get extended up to
-- * inode->i_size while the I/O was running due to writeback of delalloc
-- * blocks. But, the code in ext4_iomap_alloc() is careful to use
-- * zeroed/unwritten extents if this is possible; thus we won't leave
-- * uninitialized blocks in a file even if we didn't succeed in writing
-- * as much as we intended.
-- */
-- WARN_ON_ONCE(i_size_read(inode) < EXT4_I(inode)->i_disksize);
-- if (offset + count <= EXT4_I(inode)->i_disksize) {
-- /*
-- * We need to ensure that the inode is removed from the orphan
-- * list if it has been added prematurely, due to writeback of
-- * delalloc blocks.
-- */
-- if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
-- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
--
-- if (IS_ERR(handle)) {
-- ext4_orphan_del(NULL, inode);
-- return PTR_ERR(handle);
-- }
--
-- ext4_orphan_del(handle, inode);
-- ext4_journal_stop(handle);
-- }
--
-- return written;
-- }
--
-- if (written < 0)
-- goto truncate;
-
-+ lockdep_assert_held_write(&inode->i_rwsem);
- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
-- if (IS_ERR(handle)) {
-- written = PTR_ERR(handle);
-- goto truncate;
-- }
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-
-- if (ext4_update_inode_size(inode, offset + written)) {
-- ret = ext4_mark_inode_dirty(handle, inode);
-+ if (ext4_update_inode_size(inode, offset + count)) {
-+ int ret = ext4_mark_inode_dirty(handle, inode);
- if (unlikely(ret)) {
-- written = ret;
- ext4_journal_stop(handle);
-- goto truncate;
-+ return ret;
- }
- }
-
-- /*
-- * We may need to truncate allocated but not written blocks beyond EOF.
-- */
-- written_blk = ALIGN(offset + written, 1 << blkbits);
-- end_blk = ALIGN(offset + count, 1 << blkbits);
-- if (written_blk < end_blk && ext4_can_truncate(inode))
-- truncate = true;
--
-- /*
-- * Remove the inode from the orphan list if it has been extended and
-- * everything went OK.
-- */
-- if (!truncate && inode->i_nlink)
-+ if (inode->i_nlink)
- ext4_orphan_del(handle, inode);
- ext4_journal_stop(handle);
-
-- if (truncate) {
--truncate:
-+ return count;
-+}
-+
-+/*
-+ * Clean up the inode after DIO or DAX extending write has completed and the
-+ * inode size has been updated using ext4_handle_inode_extension().
-+ */
-+static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
-+{
-+ lockdep_assert_held_write(&inode->i_rwsem);
-+ if (count < 0) {
- ext4_truncate_failed_write(inode);
- /*
- * If the truncate operation failed early, then the inode may
-@@ -361,9 +319,28 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
- */
- if (inode->i_nlink)
- ext4_orphan_del(NULL, inode);
-+ return;
- }
-+ /*
-+ * If i_disksize got extended due to writeback of delalloc blocks while
-+ * the DIO was running we could fail to cleanup the orphan list in
-+ * ext4_handle_inode_extension(). Do it now.
-+ */
-+ if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
-+ handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
-
-- return written;
-+ if (IS_ERR(handle)) {
-+ /*
-+ * The write has successfully completed. Not much to
-+ * do with the error here so just cleanup the orphan
-+ * list and hope for the best.
-+ */
-+ ext4_orphan_del(NULL, inode);
-+ return;
-+ }
-+ ext4_orphan_del(handle, inode);
-+ ext4_journal_stop(handle);
-+ }
- }
-
- static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
-@@ -372,31 +349,22 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
- loff_t pos = iocb->ki_pos;
- struct inode *inode = file_inode(iocb->ki_filp);
-
-+ if (!error && size && flags & IOMAP_DIO_UNWRITTEN)
-+ error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
- if (error)
- return error;
--
-- if (size && flags & IOMAP_DIO_UNWRITTEN) {
-- error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
-- if (error < 0)
-- return error;
-- }
- /*
-- * If we are extending the file, we have to update i_size here before
-- * page cache gets invalidated in iomap_dio_rw(). Otherwise racing
-- * buffered reads could zero out too much from page cache pages. Update
-- * of on-disk size will happen later in ext4_dio_write_iter() where
-- * we have enough information to also perform orphan list handling etc.
-- * Note that we perform all extending writes synchronously under
-- * i_rwsem held exclusively so i_size update is safe here in that case.
-- * If the write was not extending, we cannot see pos > i_size here
-- * because operations reducing i_size like truncate wait for all
-- * outstanding DIO before updating i_size.
-+ * Note that EXT4_I(inode)->i_disksize can get extended up to
-+ * inode->i_size while the I/O was running due to writeback of delalloc
-+ * blocks. But the code in ext4_iomap_alloc() is careful to use
-+ * zeroed/unwritten extents if this is possible; thus we won't leave
-+ * uninitialized blocks in a file even if we didn't succeed in writing
-+ * as much as we intended.
- */
-- pos += size;
-- if (pos > i_size_read(inode))
-- i_size_write(inode, pos);
--
-- return 0;
-+ WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize));
-+ if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize))
-+ return size;
-+ return ext4_handle_inode_extension(inode, pos, size);
- }
-
- static const struct iomap_dio_ops ext4_dio_write_ops = {
-@@ -572,9 +540,16 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
- 0);
- if (ret == -ENOTBLK)
- ret = 0;
--
-- if (extend)
-- ret = ext4_handle_inode_extension(inode, offset, ret, count);
-+ if (extend) {
-+ /*
-+ * We always perform extending DIO write synchronously so by
-+ * now the IO is completed and ext4_handle_inode_extension()
-+ * was called. Cleanup the inode in case of error or race with
-+ * writeback of delalloc blocks.
-+ */
-+ WARN_ON_ONCE(ret == -EIOCBQUEUED);
-+ ext4_inode_extension_cleanup(inode, ret);
-+ }
-
- out:
- if (ilock_shared)
-@@ -655,8 +630,10 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
-
- ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops);
-
-- if (extend)
-- ret = ext4_handle_inode_extension(inode, offset, ret, count);
-+ if (extend) {
-+ ret = ext4_handle_inode_extension(inode, offset, ret);
-+ ext4_inode_extension_cleanup(inode, ret);
-+ }
- out:
- inode_unlock(inode);
- if (ret > 0)
---
-2.42.0
-
asoc-sof-sof-pci-dev-don-t-use-the-community-key-on-.patch
asoc-sof-sof-pci-dev-fix-community-key-quirk-detecti.patch
fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch
-ext4-properly-sync-file-size-update-after-o_sync-dir.patch
fs-add-ctime-accessors-infrastructure.patch
smb3-fix-caching-of-ctime-on-setxattr.patch
cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch
asoc-sof-sof-pci-dev-don-t-use-the-community-key-on-.patch-15789
asoc-sof-sof-pci-dev-fix-community-key-quirk-detecti.patch-6356
fbdev-stifb-make-the-sti-next-font-pointer-a-32-bit-.patch-17578
-ext4-properly-sync-file-size-update-after-o_sync-dir.patch-12628
fs-add-ctime-accessors-infrastructure.patch-279
smb3-fix-caching-of-ctime-on-setxattr.patch-25511
cpufreq-imx6q-don-t-warn-for-disabling-a-non-existin.patch-28374