]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Dec 2024 09:00:09 +0000 (10:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Dec 2024 09:00:09 +0000 (10:00 +0100)
added patches:
f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch

queue-6.6/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-6.6/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch b/queue-6.6/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch
new file mode 100644 (file)
index 0000000..b4524ff
--- /dev/null
@@ -0,0 +1,109 @@
+From a7a7c1d423a6351a6541e95c797da5358e5ad1ea Mon Sep 17 00:00:00 2001
+From: Xiuhong Wang <xiuhong.wang@unisoc.com>
+Date: Tue, 29 Oct 2024 14:15:35 +0800
+Subject: f2fs: fix fiemap failure issue when page size is 16KB
+
+From: Xiuhong Wang <xiuhong.wang@unisoc.com>
+
+commit a7a7c1d423a6351a6541e95c797da5358e5ad1ea upstream.
+
+After enable 16K page size, an infinite loop may occur in
+fiemap (fm_length=UINT64_MAX) on a file, such as the 16KB
+scratch.img during the remount operation in Android.
+
+The condition for whether fiemap continues to map is to check
+whether the number of bytes corresponding to the next map.m_lblk
+exceeds blks_to_bytes(inode,max_inode_blocks(inode)) if there are HOLE.
+The latter does not take into account the maximum size of a file with 16KB
+page size, so the loop cannot be jumped out.
+
+The following is the fail trace:
+When f2fs_map_blocks reaches map.m_lblk=3936, it needs to go to the
+first direct node block, so the map is 3936 + 4090 = 8026,
+The next map is the second direct node block, that is,
+8026 + 4090 = 12116,
+The next map is the first indirect node block, that is,
+12116 + 4090 * 4090 = 16740216,
+The next map is the second indirect node block, that is,
+16740216 + 4090 * 4090 = 33468316,
+The next map is the first double indirect node block, that is,
+33468316 + 4090 * 4090 * 4090 = 68451397316
+Since map.m_lblk represents the address of a block, which is 32
+bits, truncation will occur, that is, 68451397316 becomes
+4026887876, and the number of bytes corresponding to the block
+number does not exceed blks_to_bytes(inode,max_inode_blocks(inode)),
+so the loop will not be jumped out.
+The next time, it will be considered that it should still be a
+double indirect node block, that is,
+4026887876 + 4090 * 4090 * 4090 = 72444816876, which will be
+truncated to 3725340140, and the loop will not be jumped out.
+
+156.374871: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 0, start blkaddr = 0x8e00, len = 0x200, flags = 2,seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.374916: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 512, start blkaddr = 0x0, len = 0x0, flags = 0 , seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.374920: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 513, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+......
+156.385747: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 3935, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385752: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 3936, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385755: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 8026, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385758: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 12116, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385761: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 16740216, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385764: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 33468316, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385767: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 4026887876, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385770: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 3725340140, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385772: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 4026887876, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+156.385775: f2fs_map_blocks: dev = (254,57), ino = 7449, file offset = 3725340140, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0
+
+Commit a6a010f5def5 ("f2fs: Restrict max filesize for 16K f2fs")
+has set the maximum allowed file size to (U32_MAX + 1) * F2FS_BLKSIZE,
+so max_file_blocks should be used here to limit it, that is,
+maxbytes defined above. And the max_inode_blocks function is not
+called by other functions except here, so cleanup it.
+
+Signed-off-by: Xiuhong Wang <xiuhong.wang@unisoc.com>
+Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Cc: Daniel Rosenberg <drosen@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |   22 +---------------------
+ 1 file changed, 1 insertion(+), 21 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -1873,25 +1873,6 @@ static int f2fs_xattr_fiemap(struct inod
+       return (err < 0 ? err : 0);
+ }
+-static loff_t max_inode_blocks(struct inode *inode)
+-{
+-      loff_t result = ADDRS_PER_INODE(inode);
+-      loff_t leaf_count = ADDRS_PER_BLOCK(inode);
+-
+-      /* two direct node blocks */
+-      result += (leaf_count * 2);
+-
+-      /* two indirect node blocks */
+-      leaf_count *= NIDS_PER_BLOCK;
+-      result += (leaf_count * 2);
+-
+-      /* one double indirect node block */
+-      leaf_count *= NIDS_PER_BLOCK;
+-      result += leaf_count;
+-
+-      return result;
+-}
+-
+ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+               u64 start, u64 len)
+ {
+@@ -1964,8 +1945,7 @@ next:
+       if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
+               start_blk = next_pgofs;
+-              if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode,
+-                                              max_inode_blocks(inode)))
++              if (blks_to_bytes(inode, start_blk) < maxbytes)
+                       goto prep_next;
+               flags |= FIEMAP_EXTENT_LAST;
index 9bedc15cd69ff31638dc4f377d1e06ac8e144014..4c19a4adea0638415c201da794246ff39c3371a3 100644 (file)
@@ -450,3 +450,4 @@ apparmor-fix-do-simple-duplicate-message-elimination.patch
 asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch
 gfs2-don-t-set-glf_lock-in-gfs2_dispose_glock_lru.patch
 gfs2-remove-and-replace-gfs2_glock_queue_work.patch
+f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch