From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 12:47:15 +0000 (+0200) Subject: 7.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e4f04460e9c4a01b3730a6fe4562dd8968df9fe;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches 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 --- 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 index 0000000000..2c9b1b75c3 --- /dev/null +++ b/queue-7.1/exfat-add-balloc-parameter-to-exfat_map_cluster-for-iomap-support.patch @@ -0,0 +1,59 @@ +From stable+bounces-278558-greg=kroah.com@vger.kernel.org Tue Jul 21 13:49:57 2026 +From: Sasha Levin +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 , Christoph Hellwig , "Darrick J. Wong" , Sasha Levin +Message-ID: <20260721114656.3687966-2-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Acked-by: "Darrick J. Wong" +Signed-off-by: Namjae Jeon +Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d0bef72086 --- /dev/null +++ b/queue-7.1/exfat-add-data_start_bytes-and-exfat_cluster_to_phys_bytes-helper.patch @@ -0,0 +1,61 @@ +From stable+bounces-278559-greg=kroah.com@vger.kernel.org Tue Jul 21 13:50:02 2026 +From: Sasha Levin +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 , Christoph Hellwig , "Darrick J. Wong" , Sasha Levin +Message-ID: <20260721114656.3687966-3-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Acked-by: "Darrick J. Wong" +Signed-off-by: Namjae Jeon +Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..079a21682a --- /dev/null +++ b/queue-7.1/exfat-fix-implicit-declaration-of-brelse.patch @@ -0,0 +1,39 @@ +From stable+bounces-278560-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:06 2026 +From: Sasha Levin +Date: Tue, 21 Jul 2026 07:46:55 -0400 +Subject: exfat: fix implicit declaration of brelse() +To: stable@vger.kernel.org +Cc: Namjae Jeon , Christoph Hellwig , "Darrick J. Wong" , Sasha Levin +Message-ID: <20260721114656.3687966-4-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Acked-by: "Darrick J. Wong" +Signed-off-by: Namjae Jeon +Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + #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 index 0000000000..0bfd1496e6 --- /dev/null +++ b/queue-7.1/exfat-replace-unsafe-macros-with-static-inline-functions.patch @@ -0,0 +1,589 @@ +From stable+bounces-278557-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:03 2026 +From: Sasha Levin +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 , Christoph Hellwig , "Darrick J. Wong" , Sasha Levin +Message-ID: <20260721114656.3687966-1-sashal@kernel.org> + +From: Namjae Jeon + +[ 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 +Acked-by: "Darrick J. Wong" +Signed-off-by: Namjae Jeon +Stable-dep-of: 044472d5ee7d ("iomap: consolidate bio submission") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..409240484f --- /dev/null +++ b/queue-7.1/iomap-consolidate-bio-submission.patch @@ -0,0 +1,133 @@ +From stable+bounces-278561-greg=kroah.com@vger.kernel.org Tue Jul 21 13:47:12 2026 +From: Sasha Levin +Date: Tue, 21 Jul 2026 07:46:56 -0400 +Subject: iomap: consolidate bio submission +To: stable@vger.kernel.org +Cc: Christoph Hellwig , Namjae Jeon , "Darrick J. Wong" , Joanne Koong , "Christian Brauner (Amutable)" , Sasha Levin +Message-ID: <20260721114656.3687966-5-sashal@kernel.org> + +From: Christoph Hellwig + +[ 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 +Link: https://patch.msgid.link/20260629121750.3392300-2-hch@lst.de +Acked-by: Namjae Jeon +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Joanne Koong +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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; + diff --git a/queue-7.1/series b/queue-7.1/series index 42a1103da7..5952a84f17 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -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