From f293078c3c22764516f1ecf8faa39d7b4a50a4f8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 2 Dec 2024 10:00:27 +0100 Subject: [PATCH] 6.12-stable patches added patches: f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch --- ...failure-issue-when-page-size-is-16kb.patch | 109 ++++++++++++++++++ queue-6.12/series | 1 + 2 files changed, 110 insertions(+) create mode 100644 queue-6.12/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch diff --git a/queue-6.12/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch b/queue-6.12/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch new file mode 100644 index 00000000000..36c1c735e51 --- /dev/null +++ b/queue-6.12/f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch @@ -0,0 +1,109 @@ +From a7a7c1d423a6351a6541e95c797da5358e5ad1ea Mon Sep 17 00:00:00 2001 +From: Xiuhong Wang +Date: Tue, 29 Oct 2024 14:15:35 +0800 +Subject: f2fs: fix fiemap failure issue when page size is 16KB + +From: Xiuhong Wang + +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 +Signed-off-by: Zhiguo Niu +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Cc: Daniel Rosenberg +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/data.c | 22 +--------------------- + 1 file changed, 1 insertion(+), 21 deletions(-) + +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -1902,25 +1902,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) + { +@@ -1993,8 +1974,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; diff --git a/queue-6.12/series b/queue-6.12/series index 04e256dde50..18d6c01eb30 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -620,3 +620,4 @@ alsa-core-fix-possible-null-dereference-caused-by-ku.patch asoc-amd-yc-fix-for-enabling-dmic-on-acp6x-via-_dsd-.patch asoc-mediatek-check-num_codecs-is-not-zero-to-avoid-.patch s390-pci-fix-potential-double-remove-of-hotplug-slot.patch +f2fs-fix-fiemap-failure-issue-when-page-size-is-16kb.patch -- 2.47.3