]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 12:47:15 +0000 (14:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jul 2026 12:47:15 +0000 (14:47 +0200)
added patches:
exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch
exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch
exfat-fix-implicit-declaration-of-brelse.patch
exfat-replace-unsafe-macros-with-static-inline-functions.patch
iomap-consolidate-bio-submission.patch

queue-7.1/exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch [new file with mode: 0644]
queue-7.1/exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch [new file with mode: 0644]
queue-7.1/exfat-fix-implicit-declaration-of-brelse.patch [new file with mode: 0644]
queue-7.1/exfat-replace-unsafe-macros-with-static-inline-functions.patch [new file with mode: 0644]
queue-7.1/iomap-consolidate-bio-submission.patch [new file with mode: 0644]
queue-7.1/series

diff --git a/queue-7.1/exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch b/queue-7.1/exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch
new file mode 100644 (file)
index 0000000..2c9b1b7
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-278558-greg=kroah.com@vger.kernel.org Tue Jul 21 13:49:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:46:53 -0400
+Subject: exfat: add balloc parameter to exfat_map_cluster() for iomap support
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Christoph Hellwig <hch@lst.de>, "Darrick J. Wong" <djwong@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114656.3687966-2-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit 3474416bb9abafca2e79b7ff700a100b7e8bc766 ]
+
+In preparation for supporting the iomap infrastructure, we need to know
+whether a new cluster was allocated or not in exfat_map_cluster().
+
+Add an optional 'bool *balloc' output parameter. When a new cluster is
+allocated, *balloc is set to true. Pass NULL from exfat_get_block() to
+preserve the existing behavior.
+
+Acked-by: Christoph Hellwig <hch@lst.de>
+Acked-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exfat/inode.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/fs/exfat/inode.c
++++ b/fs/exfat/inode.c
+@@ -124,7 +124,8 @@ void exfat_sync_inode(struct inode *inod
+  * *clu = (~0), if it's unable to allocate a new cluster
+  */
+ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
+-              unsigned int *clu, unsigned int *count, int create)
++              unsigned int *clu, unsigned int *count, int create,
++              bool *balloc)
+ {
+       int ret;
+       unsigned int last_clu;
+@@ -229,6 +230,8 @@ static int exfat_map_cluster(struct inod
+               if (exfat_cluster_walk(sb, clu, num_to_be_allocated - 1, ei->flags))
+                       return -EIO;
+               *count = 1;
++              if (balloc)
++                      *balloc = true;
+       }
+       /* hint information */
+@@ -262,7 +265,7 @@ static int exfat_get_block(struct inode
+       /* Is this block already allocated? */
+       count = exfat_bytes_to_cluster_round_up(sbi, bh_result->b_size);
+       err = exfat_map_cluster(inode, iblock >> sbi->sect_per_clus_bits,
+-                      &cluster, &count, create);
++                      &cluster, &count, create, NULL);
+       if (err) {
+               if (err != -ENOSPC)
+                       exfat_fs_error_ratelimit(sb,
diff --git a/queue-7.1/exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch b/queue-7.1/exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch
new file mode 100644 (file)
index 0000000..d0bef72
--- /dev/null
@@ -0,0 +1,61 @@
+From stable+bounces-278559-greg=kroah.com@vger.kernel.org Tue Jul 21 13:50:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:46:54 -0400
+Subject: exfat: add data_start_bytes and exfat_cluster_to_phys_bytes() helper
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Christoph Hellwig <hch@lst.de>, "Darrick J. Wong" <djwong@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114656.3687966-3-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit 3b9450beeb961c7ddf4cccddba37fcfa6d1fcb7a ]
+
+This caches the data area start offset in bytes (data_start_bytes)
+and introduces a helper function exfat_cluster_to_phys_bytes() to compute
+the physical byte position of a given cluster.
+
+Acked-by: Christoph Hellwig <hch@lst.de>
+Acked-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exfat/exfat_fs.h |    8 ++++++++
+ fs/exfat/super.c    |    1 +
+ 2 files changed, 9 insertions(+)
+
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -227,6 +227,7 @@ struct exfat_sb_info {
+       unsigned long long FAT1_start_sector; /* FAT1 start sector */
+       unsigned long long FAT2_start_sector; /* FAT2 start sector */
+       unsigned long long data_start_sector; /* data area start sector */
++      unsigned long long data_start_bytes;
+       unsigned int num_FAT_sectors; /* num of FAT sectors */
+       unsigned int root_dir; /* root dir cluster */
+       unsigned int dentries_per_clu; /* num of dentries per cluster */
+@@ -400,6 +401,13 @@ static inline loff_t exfat_ondisk_size(c
+       return ((loff_t)inode->i_blocks) << 9;
+ }
++static inline loff_t exfat_cluster_to_phys_bytes(struct exfat_sb_info *sbi,
++              unsigned int clus)
++{
++      return ((loff_t)(clus - EXFAT_RESERVED_CLUSTERS) << sbi->cluster_size_bits) +
++              sbi->data_start_bytes;
++}
++
+ /*
+  * helpers for cluster size to byte conversion.
+  */
+--- a/fs/exfat/super.c
++++ b/fs/exfat/super.c
+@@ -499,6 +499,7 @@ static int exfat_read_boot_sector(struct
+       if (p_boot->num_fats == 2)
+               sbi->FAT2_start_sector += sbi->num_FAT_sectors;
+       sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset);
++      sbi->data_start_bytes = sbi->data_start_sector << p_boot->sect_size_bits;
+       sbi->num_sectors = le64_to_cpu(p_boot->vol_length);
+       /* because the cluster index starts with 2 */
+       sbi->num_clusters = le32_to_cpu(p_boot->clu_count) +
diff --git a/queue-7.1/exfat-fix-implicit-declaration-of-brelse.patch b/queue-7.1/exfat-fix-implicit-declaration-of-brelse.patch
new file mode 100644 (file)
index 0000000..079a216
--- /dev/null
@@ -0,0 +1,39 @@
+From stable+bounces-278560-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:46:55 -0400
+Subject: exfat: fix implicit declaration of brelse()
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Christoph Hellwig <hch@lst.de>, "Darrick J. Wong" <djwong@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114656.3687966-4-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit f0d1b2e1e02c11e29c953f22a485449e3da2a575 ]
+
+exfat_cluster_walk() calls brelse(bh) without including the header that
+declares the function, causing the following build error:
+
+    fs/exfat/exfat_fs.h:542:9: error: implicit declaration of function ‘brelse’ [-Werror=implicit-function-declaration]
+
+Fix this by adding the missing buffer_head.h in exfat_fs.h.
+
+Acked-by: Christoph Hellwig <hch@lst.de>
+Acked-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exfat/exfat_fs.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -12,6 +12,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/backing-dev.h>
+ #include <uapi/linux/exfat.h>
++#include <linux/buffer_head.h>
+ #define EXFAT_ROOT_INO                1
diff --git a/queue-7.1/exfat-replace-unsafe-macros-with-static-inline-functions.patch b/queue-7.1/exfat-replace-unsafe-macros-with-static-inline-functions.patch
new file mode 100644 (file)
index 0000000..0bfd149
--- /dev/null
@@ -0,0 +1,589 @@
+From stable+bounces-278557-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:03 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:46:52 -0400
+Subject: exfat: replace unsafe macros with static inline functions
+To: stable@vger.kernel.org
+Cc: Namjae Jeon <linkinjeon@kernel.org>, Christoph Hellwig <hch@lst.de>, "Darrick J. Wong" <djwong@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114656.3687966-1-sashal@kernel.org>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit f07db38084dc45162d5fe2871ed72674ddc0f9ae ]
+
+The current exFAT driver relies on various macros for unit conversions
+between clusters, blocks, sectors, and directory entries. These macros
+are structurally unsafe as they lack type enforcement and are prone to
+potential integer overflows during bit-shift operations, especially
+on 64-bit architectures. Replace all arithmetic macros with static inline
+functions to provide strict type checking and explicit casting.
+
+Acked-by: Christoph Hellwig <hch@lst.de>
+Acked-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exfat/balloc.c   |    2 
+ fs/exfat/dir.c      |   48 ++++++++++----------
+ fs/exfat/exfat_fs.h |  122 +++++++++++++++++++++++++++++++++++++---------------
+ fs/exfat/fatent.c   |    4 -
+ fs/exfat/file.c     |    8 +--
+ fs/exfat/inode.c    |   19 ++++----
+ fs/exfat/namei.c    |   26 +++++------
+ fs/exfat/super.c    |    4 -
+ 8 files changed, 147 insertions(+), 86 deletions(-)
+
+--- a/fs/exfat/balloc.c
++++ b/fs/exfat/balloc.c
+@@ -112,7 +112,7 @@ static int exfat_allocate_bitmap(struct
+       }
+       if (exfat_test_bitmap_range(sb, sbi->map_clu,
+-              EXFAT_B_TO_CLU_ROUND_UP(map_size, sbi)) == false)
++              exfat_bytes_to_cluster_round_up(sbi, map_size)) == false)
+               goto err_out;
+       return 0;
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -76,7 +76,7 @@ static int exfat_readdir(struct inode *i
+       struct super_block *sb = inode->i_sb;
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
+       struct exfat_inode_info *ei = EXFAT_I(inode);
+-      unsigned int dentry = EXFAT_B_TO_DEN(*cpos) & 0xFFFFFFFF;
++      unsigned int dentry = exfat_bytes_to_dentries(*cpos) & 0xFFFFFFFF;
+       struct buffer_head *bh;
+       /* check if the given file ID is opened */
+@@ -84,13 +84,13 @@ static int exfat_readdir(struct inode *i
+               return -EPERM;
+       exfat_chain_set(&dir, ei->start_clu,
+-              EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
++              exfat_bytes_to_cluster(sbi, i_size_read(inode)), ei->flags);
+       dentries_per_clu = sbi->dentries_per_clu;
+-      max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
+-                              (u64)EXFAT_CLU_TO_DEN(sbi->num_clusters, sbi));
++      max_dentries = min(MAX_EXFAT_DENTRIES,
++                      exfat_cluster_to_dentries(sbi, sbi->num_clusters));
+-      clu_offset = EXFAT_DEN_TO_CLU(dentry, sbi);
++      clu_offset = exfat_dentries_to_cluster(sbi, dentry);
+       exfat_chain_dup(&clu, &dir);
+       if (clu.flags == ALLOC_FAT_CHAIN) {
+@@ -147,10 +147,10 @@ static int exfat_readdir(struct inode *i
+                       dir_entry->dir = clu;
+                       brelse(bh);
+-                      ei->hint_bmap.off = EXFAT_DEN_TO_CLU(dentry, sbi);
++                      ei->hint_bmap.off = exfat_dentries_to_cluster(sbi, dentry);
+                       ei->hint_bmap.clu = clu.dir;
+-                      *cpos = EXFAT_DEN_TO_B(dentry + 1 + num_ext);
++                      *cpos = exfat_dentries_to_bytes(dentry + 1 + num_ext);
+                       return 0;
+               }
+@@ -160,7 +160,7 @@ static int exfat_readdir(struct inode *i
+ out:
+       dir_entry->namebuf.lfn[0] = '\0';
+-      *cpos = EXFAT_DEN_TO_B(dentry);
++      *cpos = exfat_dentries_to_bytes(dentry);
+       return 0;
+ }
+@@ -465,7 +465,7 @@ static void exfat_free_benign_secondary_
+               return;
+       exfat_chain_set(&dir, start_clu,
+-                      EXFAT_B_TO_CLU_ROUND_UP(size, EXFAT_SB(sb)),
++                      exfat_bytes_to_cluster_round_up(EXFAT_SB(sb), size),
+                       flags);
+       exfat_free_cluster(inode, &dir);
+ }
+@@ -594,10 +594,11 @@ static int exfat_find_location(struct su
+       unsigned int off, clu = 0;
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
+-      off = EXFAT_DEN_TO_B(entry);
++      off = exfat_dentries_to_bytes(entry);
+       clu = p_dir->dir;
+-      ret = exfat_cluster_walk(sb, &clu, EXFAT_B_TO_CLU(off, sbi), p_dir->flags);
++      ret = exfat_cluster_walk(sb, &clu, exfat_bytes_to_cluster(sbi, off),
++                      p_dir->flags);
+       if (ret)
+               return ret;
+@@ -605,7 +606,7 @@ static int exfat_find_location(struct su
+               exfat_fs_error(sb,
+                       "unexpected early break in cluster chain (clu : %u, len : %d)",
+                       p_dir->dir,
+-                      EXFAT_B_TO_CLU(off, sbi));
++                      exfat_bytes_to_cluster(sbi, off));
+               return -EIO;
+       }
+@@ -615,13 +616,13 @@ static int exfat_find_location(struct su
+       }
+       /* byte offset in cluster */
+-      off = EXFAT_CLU_OFFSET(off, sbi);
++      off = exfat_cluster_offset(sbi, off);
+       /* byte offset in sector    */
+-      *offset = EXFAT_BLK_OFFSET(off, sb);
++      *offset = exfat_block_offset(sb, off);
+       /* sector offset in cluster */
+-      *sector = EXFAT_B_TO_BLK(off, sb);
++      *sector = exfat_bytes_to_block(sb, off);
+       *sector += exfat_cluster_to_sector(sbi, clu);
+       return 0;
+ }
+@@ -631,7 +632,7 @@ struct exfat_dentry *exfat_get_dentry(st
+ {
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
+       unsigned int sect_per_clus = sbi->sect_per_clus;
+-      unsigned int dentries_per_page = EXFAT_B_TO_DEN(PAGE_SIZE);
++      unsigned int dentries_per_page = exfat_bytes_to_dentries(PAGE_SIZE);
+       int off;
+       sector_t sec;
+@@ -710,8 +711,8 @@ struct exfat_dentry *exfat_get_dentry_ca
+       struct exfat_entry_set_cache *es, int num)
+ {
+       int off = es->start_off + num * DENTRY_SIZE;
+-      struct buffer_head *bh = es->bh[EXFAT_B_TO_BLK(off, es->sb)];
+-      char *p = bh->b_data + EXFAT_BLK_OFFSET(off, es->sb);
++      struct buffer_head *bh = es->bh[exfat_bytes_to_block(es->sb, off)];
++      char *p = bh->b_data + exfat_block_offset(es->sb, off);
+       return (struct exfat_dentry *)p;
+ }
+@@ -779,7 +780,7 @@ static int __exfat_get_dentry_set(struct
+       es->num_entries = num_entries;
+-      num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
++      num_bh = exfat_bytes_to_block_round_up(sb, off + num_entries * DENTRY_SIZE);
+       if (num_bh > ARRAY_SIZE(es->__bh)) {
+               es->bh = kmalloc_objs(*es->bh, num_bh, GFP_NOFS);
+               if (!es->bh) {
+@@ -868,7 +869,7 @@ static int exfat_validate_empty_dentry_s
+ err_used_follow_unused:
+       off = es->start_off + (i << DENTRY_SIZE_BITS);
+-      bh = es->bh[EXFAT_B_TO_BLK(off, es->sb)];
++      bh = es->bh[exfat_bytes_to_block(es->sb, off)];
+       exfat_fs_error(es->sb,
+               "in sector %lld, dentry %d should be unused, but 0x%x",
+@@ -877,7 +878,8 @@ err_used_follow_unused:
+       return -EIO;
+ count_skip_entries:
+-      es->num_entries = EXFAT_B_TO_DEN(EXFAT_BLK_TO_B(es->num_bh, es->sb) - es->start_off);
++      es->num_entries =
++              exfat_bytes_to_dentries(exfat_block_to_bytes(es->sb, es->num_bh) - es->start_off);
+       for (; i < es->num_entries; i++) {
+               ep = exfat_get_dentry_cached(es, i);
+               if (IS_EXFAT_DELETED(ep->type))
+@@ -930,7 +932,7 @@ static inline void exfat_set_empty_hint(
+ {
+       if (ei->hint_femp.eidx == EXFAT_HINT_NONE ||
+           ei->hint_femp.eidx > dentry) {
+-              int total_entries = EXFAT_B_TO_DEN(i_size_read(&ei->vfs_inode));
++              int total_entries = exfat_bytes_to_dentries(i_size_read(&ei->vfs_inode));
+               if (candi_empty->count == 0) {
+                       candi_empty->cur = *clu;
+@@ -1258,7 +1260,7 @@ static int exfat_get_volume_label_dentry
+                       es->bh = es->__bh;
+                       es->bh[0] = bh;
+                       es->num_bh = 1;
+-                      es->start_off = EXFAT_DEN_TO_B(i) % sb->s_blocksize;
++                      es->start_off = exfat_dentries_to_bytes(i) % sb->s_blocksize;
+                       return 0;
+               }
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -85,38 +85,6 @@ enum {
+       << (PAGE_SHIFT - (sb)->s_blocksize_bits))
+ /*
+- * helpers for cluster size to byte conversion.
+- */
+-#define EXFAT_CLU_TO_B(b, sbi)                ((b) << (sbi)->cluster_size_bits)
+-#define EXFAT_B_TO_CLU(b, sbi)                ((b) >> (sbi)->cluster_size_bits)
+-#define EXFAT_B_TO_CLU_ROUND_UP(b, sbi)       \
+-      (((b - 1) >> (sbi)->cluster_size_bits) + 1)
+-#define EXFAT_CLU_OFFSET(off, sbi)    ((off) & ((sbi)->cluster_size - 1))
+-
+-/*
+- * helpers for block size to byte conversion.
+- */
+-#define EXFAT_BLK_TO_B(b, sb)         ((b) << (sb)->s_blocksize_bits)
+-#define EXFAT_B_TO_BLK(b, sb)         ((b) >> (sb)->s_blocksize_bits)
+-#define EXFAT_B_TO_BLK_ROUND_UP(b, sb)        \
+-      (((b - 1) >> (sb)->s_blocksize_bits) + 1)
+-#define EXFAT_BLK_OFFSET(off, sb)     ((off) & ((sb)->s_blocksize - 1))
+-
+-/*
+- * helpers for block size to dentry size conversion.
+- */
+-#define EXFAT_B_TO_DEN(b)             ((b) >> DENTRY_SIZE_BITS)
+-#define EXFAT_DEN_TO_B(b)             ((b) << DENTRY_SIZE_BITS)
+-
+-/*
+- * helpers for cluster size to dentry size conversion.
+- */
+-#define EXFAT_CLU_TO_DEN(clu, sbi)    \
+-      ((clu) << ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS))
+-#define EXFAT_DEN_TO_CLU(dentry, sbi) \
+-      ((dentry) >> ((sbi)->cluster_size_bits - DENTRY_SIZE_BITS))
+-
+-/*
+  * helpers for fat entry.
+  */
+ #define FAT_ENT_SIZE (4)
+@@ -149,7 +117,7 @@ enum {
+  * The 608 bytes are in 3 sectors at most (even 512 Byte sector).
+  */
+ #define DIR_CACHE_SIZE                \
+-      (DIV_ROUND_UP(EXFAT_DEN_TO_B(ES_MAX_ENTRY_NUM), SECTOR_SIZE) + 1)
++      (DIV_ROUND_UP(ES_MAX_ENTRY_NUM << DENTRY_SIZE_BITS, SECTOR_SIZE) + 1)
+ /* Superblock flags */
+ #define EXFAT_FLAGS_SHUTDOWN  1
+@@ -432,6 +400,94 @@ static inline loff_t exfat_ondisk_size(c
+       return ((loff_t)inode->i_blocks) << 9;
+ }
++/*
++ * helpers for cluster size to byte conversion.
++ */
++static inline loff_t exfat_cluster_to_bytes(struct exfat_sb_info *sbi,
++              u32 nr_clusters)
++{
++      return (loff_t)nr_clusters << sbi->cluster_size_bits;
++}
++
++static inline blkcnt_t exfat_cluster_to_sectors(struct exfat_sb_info *sbi,
++              u32 nr_clusters)
++{
++      return (blkcnt_t)nr_clusters << (sbi->cluster_size_bits - 9);
++}
++
++static inline u32 exfat_bytes_to_cluster(struct exfat_sb_info *sbi, loff_t size)
++{
++      return (u32)(size >> sbi->cluster_size_bits);
++}
++
++static inline u32 exfat_bytes_to_cluster_round_up(struct exfat_sb_info *sbi,
++              loff_t size)
++{
++      if (size <= 0)
++              return 0;
++      return (u32)((size - 1) >> sbi->cluster_size_bits) + 1;
++}
++
++static inline u32 exfat_cluster_offset(struct exfat_sb_info *sbi, loff_t off)
++{
++      return off & (sbi->cluster_size - 1);
++}
++
++/*
++ * helpers for block size to byte conversion.
++ */
++static inline loff_t exfat_block_to_bytes(struct super_block *sb,
++              sector_t block)
++{
++      return (loff_t)block << sb->s_blocksize_bits;
++}
++
++static inline sector_t exfat_bytes_to_block(struct super_block *sb, loff_t size)
++{
++      return (sector_t)(size >> sb->s_blocksize_bits);
++}
++
++static inline sector_t exfat_bytes_to_block_round_up(struct super_block *sb,
++              loff_t size)
++{
++      if (size <= 0)
++              return 0;
++      return (sector_t)(((size - 1) >> sb->s_blocksize_bits) + 1);
++}
++
++static inline u32 exfat_block_offset(struct super_block *sb, loff_t off)
++{
++      return (u32)(off & (sb->s_blocksize - 1));
++}
++
++/*
++ * helpers for block size to dentry size conversion.
++ */
++static inline u32 exfat_bytes_to_dentries(loff_t b)
++{
++      return (u32)(b >> DENTRY_SIZE_BITS);
++}
++
++static inline u32 exfat_dentries_to_bytes(u32 dentry)
++{
++      return dentry << DENTRY_SIZE_BITS;
++}
++
++/*
++ * helpers for cluster size to dentry size conversion.
++ */
++static inline u32 exfat_cluster_to_dentries(struct exfat_sb_info *sbi,
++              u32 nr_clusters)
++{
++      return nr_clusters << (sbi->cluster_size_bits - DENTRY_SIZE_BITS);
++}
++
++static inline u32 exfat_dentries_to_cluster(struct exfat_sb_info *sbi,
++              u32 dentry)
++{
++      return dentry >> (sbi->cluster_size_bits - DENTRY_SIZE_BITS);
++}
++
+ /* super.c */
+ int exfat_set_volume_dirty(struct super_block *sb);
+ int exfat_clear_volume_dirty(struct super_block *sb);
+--- a/fs/exfat/fatent.c
++++ b/fs/exfat/fatent.c
+@@ -412,8 +412,8 @@ int exfat_zeroed_cluster(struct inode *d
+       if (IS_DIRSYNC(dir))
+               return sync_blockdev_range(sb->s_bdev,
+-                              EXFAT_BLK_TO_B(blknr, sb),
+-                              EXFAT_BLK_TO_B(last_blknr, sb) - 1);
++                              exfat_block_to_bytes(sb, blknr),
++                              exfat_block_to_bytes(sb, last_blknr) - 1);
+       return 0;
+ }
+--- a/fs/exfat/file.c
++++ b/fs/exfat/file.c
+@@ -33,9 +33,9 @@ static int exfat_cont_expand(struct inod
+       if (ret)
+               return ret;
+-      num_clusters = EXFAT_B_TO_CLU(exfat_ondisk_size(inode), sbi);
++      num_clusters = exfat_bytes_to_cluster(sbi, exfat_ondisk_size(inode));
+       /* integer overflow is already checked in inode_newsize_ok(). */
+-      new_num_clusters = EXFAT_B_TO_CLU_ROUND_UP(size, sbi);
++      new_num_clusters = exfat_bytes_to_cluster_round_up(sbi, size);
+       if (new_num_clusters == num_clusters)
+               goto out;
+@@ -200,8 +200,8 @@ int __exfat_truncate(struct inode *inode
+       exfat_set_volume_dirty(sb);
+-      num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi);
+-      num_clusters_phys = EXFAT_B_TO_CLU(exfat_ondisk_size(inode), sbi);
++      num_clusters_new = exfat_bytes_to_cluster_round_up(sbi, i_size_read(inode));
++      num_clusters_phys = exfat_bytes_to_cluster(sbi, exfat_ondisk_size(inode));
+       exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags);
+--- a/fs/exfat/inode.c
++++ b/fs/exfat/inode.c
+@@ -135,7 +135,7 @@ static int exfat_map_cluster(struct inod
+       unsigned int local_clu_offset = clu_offset;
+       unsigned int num_to_be_allocated = 0, num_clusters;
+-      num_clusters = EXFAT_B_TO_CLU(exfat_ondisk_size(inode), sbi);
++      num_clusters = exfat_bytes_to_cluster(sbi, exfat_ondisk_size(inode));
+       if (clu_offset >= num_clusters)
+               num_to_be_allocated = clu_offset - num_clusters + 1;
+@@ -216,7 +216,8 @@ static int exfat_map_cluster(struct inod
+               *clu = new_clu.dir;
+-              inode->i_blocks += EXFAT_CLU_TO_B(num_to_be_allocated, sbi) >> 9;
++              inode->i_blocks +=
++                      exfat_cluster_to_sectors(sbi, num_to_be_allocated);
+               /*
+                * Move *clu pointer along FAT chains (hole care) because the
+@@ -254,12 +255,12 @@ static int exfat_get_block(struct inode
+       mutex_lock(&sbi->s_lock);
+       i_size = i_size_read(inode);
+-      last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb);
++      last_block = exfat_bytes_to_block_round_up(sb, i_size);
+       if (iblock >= last_block && !create)
+               goto done;
+       /* Is this block already allocated? */
+-      count = EXFAT_B_TO_CLU_ROUND_UP(bh_result->b_size, sbi);
++      count = exfat_bytes_to_cluster_round_up(sbi, bh_result->b_size);
+       err = exfat_map_cluster(inode, iblock >> sbi->sect_per_clus_bits,
+                       &cluster, &count, create);
+       if (err) {
+@@ -296,9 +297,9 @@ static int exfat_get_block(struct inode
+        * care the last nested block if valid_size is not equal to i_size.
+        */
+       if (i_size == ei->valid_size || create || !bh_result->b_folio)
+-              valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb);
++              valid_blks = exfat_bytes_to_block_round_up(sb, ei->valid_size);
+       else
+-              valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
++              valid_blks = exfat_bytes_to_block(sb, ei->valid_size);
+       /* The range has been fully written, map it */
+       if (iblock + max_blocks < valid_blks)
+@@ -313,7 +314,7 @@ static int exfat_get_block(struct inode
+       /* The area has not been written, map and mark as new for create case */
+       if (create) {
+               set_buffer_new(bh_result);
+-              ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
++              ei->valid_size = exfat_block_to_bytes(sb, iblock + max_blocks);
+               mark_inode_dirty(inode);
+               goto done;
+       }
+@@ -343,7 +344,7 @@ static int exfat_get_block(struct inode
+                       goto done;
+               }
+-              pos = EXFAT_BLK_TO_B(iblock, sb);
++              pos = exfat_block_to_bytes(sb, iblock);
+               size = ei->valid_size - pos;
+               addr = folio_address(bh_result->b_folio) +
+                       offset_in_folio(bh_result->b_folio, pos);
+@@ -374,7 +375,7 @@ static int exfat_get_block(struct inode
+        */
+       clear_buffer_mapped(bh_result);
+ done:
+-      bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
++      bh_result->b_size = exfat_block_to_bytes(sb, max_blocks);
+       if (err < 0)
+               clear_buffer_mapped(bh_result);
+ unlock_ret:
+--- a/fs/exfat/namei.c
++++ b/fs/exfat/namei.c
+@@ -208,7 +208,7 @@ static int exfat_search_empty_slot(struc
+       int dentries_per_clu;
+       struct exfat_chain clu;
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
+-      int total_entries = EXFAT_CLU_TO_DEN(p_dir->size, sbi);
++      unsigned int total_entries = exfat_cluster_to_dentries(sbi, p_dir->size);
+       dentries_per_clu = sbi->dentries_per_clu;
+@@ -266,7 +266,7 @@ static int exfat_search_empty_slot(struc
+ static int exfat_check_max_dentries(struct inode *inode)
+ {
+-      if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) {
++      if (exfat_bytes_to_dentries(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) {
+               /*
+                * exFAT spec allows a dir to grow up to 8388608(256MB)
+                * dentries
+@@ -314,7 +314,8 @@ int exfat_find_empty_entry(struct inode
+       }
+       exfat_chain_set(p_dir, ei->start_clu,
+-                      EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
++                      exfat_bytes_to_cluster(sbi, i_size_read(inode)),
++                      ei->flags);
+       while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir,
+                                       num_entries, es)) < 0) {
+@@ -375,7 +376,7 @@ int exfat_find_empty_entry(struct inode
+               hint_femp.cur.size++;
+               p_dir->size++;
+-              size = EXFAT_CLU_TO_B(p_dir->size, sbi);
++              size = exfat_cluster_to_bytes(sbi, p_dir->size);
+               /* directory inode should be updated in here */
+               i_size_write(inode, size);
+@@ -604,7 +605,7 @@ static int exfat_find(struct inode *dir,
+               return ret;
+       exfat_chain_set(&cdir, ei->start_clu,
+-              EXFAT_B_TO_CLU(i_size_read(dir), sbi), ei->flags);
++              exfat_bytes_to_cluster(sbi, i_size_read(dir)), ei->flags);
+       /* check the validation of hint_stat and initialize it if required */
+       if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) {
+@@ -681,7 +682,7 @@ static int exfat_find(struct inode *dir,
+               return -EIO;
+       }
+-      if (unlikely(EXFAT_B_TO_CLU_ROUND_UP(info->size, sbi) > sbi->used_clusters)) {
++      if (unlikely(exfat_bytes_to_cluster_round_up(sbi, info->size) > sbi->used_clusters)) {
+               exfat_fs_error(sb, "data size is invalid(%lld)", info->size);
+               return -EIO;
+       }
+@@ -695,7 +696,8 @@ static int exfat_find(struct inode *dir,
+       if (info->type == TYPE_DIR) {
+               exfat_chain_set(&cdir, info->start_clu,
+-                              EXFAT_B_TO_CLU(info->size, sbi), info->flags);
++                              exfat_bytes_to_cluster(sbi, info->size),
++                              info->flags);
+               count = exfat_count_dir_entries(sb, &cdir);
+               if (count < 0)
+                       return -EIO;
+@@ -951,7 +953,7 @@ static int exfat_rmdir(struct inode *dir
+       }
+       exfat_chain_set(&clu_to_free, ei->start_clu,
+-              EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags);
++              exfat_bytes_to_cluster_round_up(sbi, i_size_read(inode)), ei->flags);
+       err = exfat_check_dir_empty(sb, &clu_to_free);
+       if (err) {
+@@ -1207,8 +1209,8 @@ static int __exfat_rename(struct inode *
+                       new_clu.dir = new_ei->start_clu;
+                       new_clu.size =
+-                              EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode),
+-                              sbi);
++                              exfat_bytes_to_cluster_round_up(sbi,
++                                              i_size_read(new_inode));
+                       new_clu.flags = new_ei->flags;
+                       ret = exfat_check_dir_empty(sb, &new_clu);
+@@ -1252,8 +1254,8 @@ static int __exfat_rename(struct inode *
+                       struct exfat_chain new_clu_to_free;
+                       exfat_chain_set(&new_clu_to_free, new_ei->start_clu,
+-                              EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode),
+-                              sbi), new_ei->flags);
++                              exfat_bytes_to_cluster_round_up(sbi, i_size_read(new_inode)),
++                              new_ei->flags);
+                       if (exfat_free_cluster(new_inode, &new_clu_to_free)) {
+                               /* just set I/O error only */
+--- a/fs/exfat/super.c
++++ b/fs/exfat/super.c
+@@ -369,7 +369,7 @@ static int exfat_read_root(struct inode
+       ei->hint_stat.clu = sbi->root_dir;
+       ei->hint_femp.eidx = EXFAT_HINT_NONE;
+-      i_size_write(inode, EXFAT_CLU_TO_B(root_clu->size, sbi));
++      i_size_write(inode, exfat_cluster_to_bytes(sbi, root_clu->size));
+       num_subdirs = exfat_count_dir_entries(sb, root_clu);
+       if (num_subdirs < 0)
+@@ -538,7 +538,7 @@ static int exfat_read_boot_sector(struct
+        * machines.
+        */
+       sb->s_maxbytes = min(MAX_LFS_FILESIZE,
+-                           EXFAT_CLU_TO_B((loff_t)EXFAT_MAX_NUM_CLUSTER, sbi));
++                           exfat_cluster_to_bytes(sbi, (loff_t)EXFAT_MAX_NUM_CLUSTER));
+       /* check logical sector size */
+       if (exfat_calibrate_blocksize(sb, 1 << p_boot->sect_size_bits))
diff --git a/queue-7.1/iomap-consolidate-bio-submission.patch b/queue-7.1/iomap-consolidate-bio-submission.patch
new file mode 100644 (file)
index 0000000..4092404
--- /dev/null
@@ -0,0 +1,133 @@
+From stable+bounces-278561-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:46:56 -0400
+Subject: iomap: consolidate bio submission
+To: stable@vger.kernel.org
+Cc: Christoph Hellwig <hch@lst.de>, Namjae Jeon <linkinjeon@kernel.org>, "Darrick J. Wong" <djwong@kernel.org>, Joanne Koong <joannelkoong@gmail.com>, "Christian Brauner (Amutable)" <brauner@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114656.3687966-5-sashal@kernel.org>
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 044472d5ee7d71f918fa3f61bd65e4933a0c006e ]
+
+Add a iomap_bio_submit_read_endio helper factored out of
+iomap_bio_submit_read to that all ->submit_read implementations for
+iomap_read_ops that use iomap_bio_read_folio_range can shared the
+logic.
+
+Right now that logic is mostly trivial, but already has a bug for XFS
+because the XFS version is too trivial:  file system integrity validation
+needs a workqueue context and thus can't happen from the default iomap
+bi_end_io I/O handler.  Unfortunately the iomap refactoring just before
+fs integrity landed moved code around here and the call go misplaced,
+meaning it never got called.  The PI information still is verified by
+the block layer, but the offloading is less efficient (and the future
+userspace interface can't get at it).
+
+Fixes: 0b10a370529c ("iomap: support T10 protection information")
+Cc: stable@vger.kernel.org # v7.1
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260629121750.3392300-2-hch@lst.de
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/iomap/bio.c        |   13 ++++++++++---
+ fs/ntfs/aops.c        |    6 ++----
+ fs/ntfs3/inode.c      |    5 +----
+ fs/xfs/xfs_aops.c     |    3 +--
+ include/linux/iomap.h |    2 ++
+ 5 files changed, 16 insertions(+), 13 deletions(-)
+
+--- a/fs/iomap/bio.c
++++ b/fs/iomap/bio.c
+@@ -78,15 +78,23 @@ u32 iomap_finish_ioend_buffered_read(str
+       return __iomap_read_end_io(&ioend->io_bio, ioend->io_error);
+ }
+-static void iomap_bio_submit_read(const struct iomap_iter *iter,
+-              struct iomap_read_folio_ctx *ctx)
++void iomap_bio_submit_read_endio(const struct iomap_iter *iter,
++              struct iomap_read_folio_ctx *ctx, bio_end_io_t end_io)
+ {
+       struct bio *bio = ctx->read_ctx;
++      bio->bi_end_io = end_io;
+       if (iter->iomap.flags & IOMAP_F_INTEGRITY)
+               fs_bio_integrity_alloc(bio);
+       submit_bio(bio);
+ }
++EXPORT_SYMBOL_GPL(iomap_bio_submit_read_endio);
++
++static void iomap_bio_submit_read(const struct iomap_iter *iter,
++              struct iomap_read_folio_ctx *ctx)
++{
++      return iomap_bio_submit_read_endio(iter, ctx, iomap_read_end_io);
++}
+ static struct bio_set *iomap_read_bio_set(struct iomap_read_folio_ctx *ctx)
+ {
+@@ -127,7 +135,6 @@ static void iomap_read_alloc_bio(const s
+       if (ctx->rac)
+               bio->bi_opf |= REQ_RAHEAD;
+       bio->bi_iter.bi_sector = iomap_sector(iomap, iter->pos);
+-      bio->bi_end_io = iomap_read_end_io;
+       bio_add_folio_nofail(bio, folio, plen,
+                       offset_in_folio(folio, iter->pos));
+       ctx->read_ctx = bio;
+--- a/fs/ntfs/aops.c
++++ b/fs/ntfs/aops.c
+@@ -38,11 +38,9 @@ static void ntfs_iomap_read_end_io(struc
+ }
+ static void ntfs_iomap_bio_submit_read(const struct iomap_iter *iter,
+-      struct iomap_read_folio_ctx *ctx)
++              struct iomap_read_folio_ctx *ctx)
+ {
+-      struct bio *bio = ctx->read_ctx;
+-      bio->bi_end_io = ntfs_iomap_read_end_io;
+-      submit_bio(bio);
++      iomap_bio_submit_read_endio(iter, ctx, ntfs_iomap_read_end_io);
+ }
+ static const struct iomap_read_ops ntfs_iomap_bio_read_ops = {
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -609,10 +609,7 @@ static void ntfs_iomap_read_end_io(struc
+ static void ntfs_iomap_bio_submit_read(const struct iomap_iter *iter,
+               struct iomap_read_folio_ctx *ctx)
+ {
+-      struct bio *bio = ctx->read_ctx;
+-
+-      bio->bi_end_io = ntfs_iomap_read_end_io;
+-      submit_bio(bio);
++      iomap_bio_submit_read_endio(iter, ctx, ntfs_iomap_read_end_io);
+ }
+ static const struct iomap_read_ops ntfs_iomap_bio_read_ops = {
+--- a/fs/xfs/xfs_aops.c
++++ b/fs/xfs/xfs_aops.c
+@@ -753,8 +753,7 @@ xfs_bio_submit_read(
+       /* defer read completions to the ioend workqueue */
+       iomap_init_ioend(iter->inode, bio, ctx->read_ctx_file_offset, 0);
+-      bio->bi_end_io = xfs_end_bio;
+-      submit_bio(bio);
++      iomap_bio_submit_read_endio(iter, ctx, xfs_end_bio);
+ }
+ static const struct iomap_read_ops xfs_iomap_read_ops = {
+--- a/include/linux/iomap.h
++++ b/include/linux/iomap.h
+@@ -615,6 +615,8 @@ extern struct bio_set iomap_ioend_bioset
+ #ifdef CONFIG_BLOCK
+ int iomap_bio_read_folio_range(const struct iomap_iter *iter,
+               struct iomap_read_folio_ctx *ctx, size_t plen);
++void iomap_bio_submit_read_endio(const struct iomap_iter *iter,
++              struct iomap_read_folio_ctx *ctx, bio_end_io_t end_io);
+ extern const struct iomap_read_ops iomap_bio_read_ops;
index 42a1103da7011c4ad66246f1d7bdbafb4e196e7a..5952a84f17577bd03bab653f001e348b2529b173 100644 (file)
@@ -2067,3 +2067,8 @@ usb-atm-ueagle-atm-remove-function-entry-exit-debug-messages.patch
 usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch
 liveupdate-validate-session-type-before-performing-operation.patch
 crypto-xilinx-trng-remove-crypto_rng-interface.patch
+exfat-replace-unsafe-macros-with-static-inline-functions.patch
+exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch
+exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch
+exfat-fix-implicit-declaration-of-brelse.patch
+iomap-consolidate-bio-submission.patch