From: Greg Kroah-Hartman Date: Tue, 21 Jan 2025 13:30:50 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v5.15.177~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a621caf3409529692f6bbef2397c827172407df1;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: erofs-handle-nonhead-delta-lclusters-gracefully.patch erofs-tidy-up-erofs-on-disk-naming.patch wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch --- diff --git a/queue-6.1/erofs-handle-nonhead-delta-lclusters-gracefully.patch b/queue-6.1/erofs-handle-nonhead-delta-lclusters-gracefully.patch new file mode 100644 index 0000000000..0e80837462 --- /dev/null +++ b/queue-6.1/erofs-handle-nonhead-delta-lclusters-gracefully.patch @@ -0,0 +1,85 @@ +From 0bc8061ffc733a0a246b8689b2d32a3e9204f43c Mon Sep 17 00:00:00 2001 +From: Gao Xiang +Date: Sat, 16 Nov 2024 01:36:51 +0800 +Subject: erofs: handle NONHEAD !delta[1] lclusters gracefully + +From: Gao Xiang + +commit 0bc8061ffc733a0a246b8689b2d32a3e9204f43c upstream. + +syzbot reported a WARNING in iomap_iter_done: + iomap_fiemap+0x73b/0x9b0 fs/iomap/fiemap.c:80 + ioctl_fiemap fs/ioctl.c:220 [inline] + +Generally, NONHEAD lclusters won't have delta[1]==0, except for crafted +images and filesystems created by pre-1.0 mkfs versions. + +Previously, it would immediately bail out if delta[1]==0, which led to +inadequate decompressed lengths (thus FIEMAP is impacted). Treat it as +delta[1]=1 to work around these legacy mkfs versions. + +`lclusterbits > 14` is illegal for compact indexes, error out too. + +Reported-by: syzbot+6c0b301317aa0156f9eb@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/r/67373c0c.050a0220.2a2fcc.0079.GAE@google.com +Tested-by: syzbot+6c0b301317aa0156f9eb@syzkaller.appspotmail.com +Fixes: d95ae5e25326 ("erofs: add support for the full decompressed length") +Fixes: 001b8ccd0650 ("erofs: fix compact 4B support for 16k block size") +Signed-off-by: Gao Xiang +Link: https://lore.kernel.org/r/20241115173651.3339514-1-hsiangkao@linux.alibaba.com +Signed-off-by: Greg Kroah-Hartman +--- + fs/erofs/zmap.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -256,7 +256,7 @@ static int compacted_load_cluster_from_d + unsigned int amortizedshift; + erofs_off_t pos; + +- if (lcn >= totalidx) ++ if (lcn >= totalidx || vi->z_logical_clusterbits > 14) + return -EINVAL; + + m->lcn = lcn; +@@ -441,7 +441,7 @@ static int z_erofs_get_extent_decompress + u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits; + int err; + +- do { ++ while (1) { + /* handle the last EOF pcluster (no next HEAD lcluster) */ + if ((lcn << lclusterbits) >= inode->i_size) { + map->m_llen = inode->i_size - map->m_la; +@@ -453,14 +453,16 @@ static int z_erofs_get_extent_decompress + return err; + + if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { +- DBG_BUGON(!m->delta[1] && +- m->clusterofs != 1 << lclusterbits); ++ /* work around invalid d1 generated by pre-1.0 mkfs */ ++ if (unlikely(!m->delta[1])) { ++ m->delta[1] = 1; ++ DBG_BUGON(1); ++ } + } else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN || + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 || + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) { +- /* go on until the next HEAD lcluster */ + if (lcn != headlcn) +- break; ++ break; /* ends at the next HEAD lcluster */ + m->delta[1] = 1; + } else { + erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu", +@@ -469,8 +471,7 @@ static int z_erofs_get_extent_decompress + return -EOPNOTSUPP; + } + lcn += m->delta[1]; +- } while (m->delta[1]); +- ++ } + map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la; + return 0; + } diff --git a/queue-6.1/erofs-tidy-up-erofs-on-disk-naming.patch b/queue-6.1/erofs-tidy-up-erofs-on-disk-naming.patch new file mode 100644 index 0000000000..0471e22603 --- /dev/null +++ b/queue-6.1/erofs-tidy-up-erofs-on-disk-naming.patch @@ -0,0 +1,602 @@ +From 1c7f49a76773bcf95d3c840cff6cd449114ddf56 Mon Sep 17 00:00:00 2001 +From: Gao Xiang +Date: Fri, 31 Mar 2023 14:31:49 +0800 +Subject: erofs: tidy up EROFS on-disk naming + +From: Gao Xiang + +commit 1c7f49a76773bcf95d3c840cff6cd449114ddf56 upstream. + + - Get rid of all "vle" (variable-length extents) expressions + since they only expand overall name lengths unnecessarily; + - Rename COMPRESSION_LEGACY to COMPRESSED_FULL; + - Move on-disk directory definitions ahead of compression; + - Drop unused extended attribute definitions; + - Move inode ondisk union `i_u` out as `union erofs_inode_i_u`. + +No actual logical change. + +Signed-off-by: Gao Xiang +Reviewed-by: Yue Hu +Reviewed-by: Chao Yu +Link: https://lore.kernel.org/r/20230331063149.25611-1-hsiangkao@linux.alibaba.com +Signed-off-by: Greg Kroah-Hartman +--- + fs/erofs/erofs_fs.h | 145 ++++++++++++++++++++++------------------------------ + fs/erofs/zmap.c | 116 ++++++++++++++++++++--------------------- + 2 files changed, 119 insertions(+), 142 deletions(-) + +--- a/fs/erofs/erofs_fs.h ++++ b/fs/erofs/erofs_fs.h +@@ -82,32 +82,27 @@ struct erofs_super_block { + }; + + /* +- * erofs inode datalayout (i_format in on-disk inode): ++ * EROFS inode datalayout (i_format in on-disk inode): + * 0 - uncompressed flat inode without tail-packing inline data: +- * inode, [xattrs], ... | ... | no-holed data + * 1 - compressed inode with non-compact indexes: +- * inode, [xattrs], [map_header], extents ... | ... + * 2 - uncompressed flat inode with tail-packing inline data: +- * inode, [xattrs], tailpacking data, ... | ... | no-holed data + * 3 - compressed inode with compact indexes: +- * inode, [xattrs], map_header, extents ... | ... + * 4 - chunk-based inode with (optional) multi-device support: +- * inode, [xattrs], chunk indexes ... | ... + * 5~7 - reserved + */ + enum { + EROFS_INODE_FLAT_PLAIN = 0, +- EROFS_INODE_FLAT_COMPRESSION_LEGACY = 1, ++ EROFS_INODE_COMPRESSED_FULL = 1, + EROFS_INODE_FLAT_INLINE = 2, +- EROFS_INODE_FLAT_COMPRESSION = 3, ++ EROFS_INODE_COMPRESSED_COMPACT = 3, + EROFS_INODE_CHUNK_BASED = 4, + EROFS_INODE_DATALAYOUT_MAX + }; + + static inline bool erofs_inode_is_data_compressed(unsigned int datamode) + { +- return datamode == EROFS_INODE_FLAT_COMPRESSION || +- datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; ++ return datamode == EROFS_INODE_COMPRESSED_COMPACT || ++ datamode == EROFS_INODE_COMPRESSED_FULL; + } + + /* bit definitions of inode i_format */ +@@ -128,11 +123,30 @@ static inline bool erofs_inode_is_data_c + #define EROFS_CHUNK_FORMAT_ALL \ + (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES) + ++/* 32-byte on-disk inode */ ++#define EROFS_INODE_LAYOUT_COMPACT 0 ++/* 64-byte on-disk inode */ ++#define EROFS_INODE_LAYOUT_EXTENDED 1 ++ + struct erofs_inode_chunk_info { + __le16 format; /* chunk blkbits, etc. */ + __le16 reserved; + }; + ++union erofs_inode_i_u { ++ /* total compressed blocks for compressed inodes */ ++ __le32 compressed_blocks; ++ ++ /* block address for uncompressed flat inodes */ ++ __le32 raw_blkaddr; ++ ++ /* for device files, used to indicate old/new device # */ ++ __le32 rdev; ++ ++ /* for chunk-based files, it contains the summary info */ ++ struct erofs_inode_chunk_info c; ++}; ++ + /* 32-byte reduced form of an ondisk inode */ + struct erofs_inode_compact { + __le16 i_format; /* inode format hints */ +@@ -143,29 +157,14 @@ struct erofs_inode_compact { + __le16 i_nlink; + __le32 i_size; + __le32 i_reserved; +- union { +- /* total compressed blocks for compressed inodes */ +- __le32 compressed_blocks; +- /* block address for uncompressed flat inodes */ +- __le32 raw_blkaddr; +- +- /* for device files, used to indicate old/new device # */ +- __le32 rdev; +- +- /* for chunk-based files, it contains the summary info */ +- struct erofs_inode_chunk_info c; +- } i_u; +- __le32 i_ino; /* only used for 32-bit stat compatibility */ ++ union erofs_inode_i_u i_u; ++ ++ __le32 i_ino; /* only used for 32-bit stat compatibility */ + __le16 i_uid; + __le16 i_gid; + __le32 i_reserved2; + }; + +-/* 32-byte on-disk inode */ +-#define EROFS_INODE_LAYOUT_COMPACT 0 +-/* 64-byte on-disk inode */ +-#define EROFS_INODE_LAYOUT_EXTENDED 1 +- + /* 64-byte complete form of an ondisk inode */ + struct erofs_inode_extended { + __le16 i_format; /* inode format hints */ +@@ -175,22 +174,9 @@ struct erofs_inode_extended { + __le16 i_mode; + __le16 i_reserved; + __le64 i_size; +- union { +- /* total compressed blocks for compressed inodes */ +- __le32 compressed_blocks; +- /* block address for uncompressed flat inodes */ +- __le32 raw_blkaddr; +- +- /* for device files, used to indicate old/new device # */ +- __le32 rdev; +- +- /* for chunk-based files, it contains the summary info */ +- struct erofs_inode_chunk_info c; +- } i_u; +- +- /* only used for 32-bit stat compatibility */ +- __le32 i_ino; ++ union erofs_inode_i_u i_u; + ++ __le32 i_ino; /* only used for 32-bit stat compatibility */ + __le32 i_uid; + __le32 i_gid; + __le64 i_mtime; +@@ -199,10 +185,6 @@ struct erofs_inode_extended { + __u8 i_reserved2[16]; + }; + +-#define EROFS_MAX_SHARED_XATTRS (128) +-/* h_shared_count between 129 ... 255 are special # */ +-#define EROFS_SHARED_XATTR_EXTENT (255) +- + /* + * inline xattrs (n == i_xattr_icount): + * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes +@@ -268,6 +250,22 @@ struct erofs_inode_chunk_index { + __le32 blkaddr; /* start block address of this inode chunk */ + }; + ++/* dirent sorts in alphabet order, thus we can do binary search */ ++struct erofs_dirent { ++ __le64 nid; /* node number */ ++ __le16 nameoff; /* start offset of file name */ ++ __u8 file_type; /* file type */ ++ __u8 reserved; /* reserved */ ++} __packed; ++ ++/* ++ * EROFS file types should match generic FT_* types and ++ * it seems no need to add BUILD_BUG_ONs since potential ++ * unmatchness will break other fses as well... ++ */ ++ ++#define EROFS_NAME_LEN 255 ++ + /* maximum supported size of a physical compression cluster */ + #define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) + +@@ -337,10 +335,8 @@ struct z_erofs_map_header { + __u8 h_clusterbits; + }; + +-#define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8 +- + /* +- * Fixed-sized output compression on-disk logical cluster type: ++ * On-disk logical cluster type: + * 0 - literal (uncompressed) lcluster + * 1,3 - compressed lcluster (for HEAD lclusters) + * 2 - compressed lcluster (for NONHEAD lclusters) +@@ -364,27 +360,27 @@ struct z_erofs_map_header { + * di_u.delta[1] = distance to the next HEAD lcluster + */ + enum { +- Z_EROFS_VLE_CLUSTER_TYPE_PLAIN = 0, +- Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 = 1, +- Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD = 2, +- Z_EROFS_VLE_CLUSTER_TYPE_HEAD2 = 3, +- Z_EROFS_VLE_CLUSTER_TYPE_MAX ++ Z_EROFS_LCLUSTER_TYPE_PLAIN = 0, ++ Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1, ++ Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2, ++ Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3, ++ Z_EROFS_LCLUSTER_TYPE_MAX + }; + +-#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2 +-#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0 ++#define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2 ++#define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0 + + /* (noncompact only, HEAD) This pcluster refers to partial decompressed data */ +-#define Z_EROFS_VLE_DI_PARTIAL_REF (1 << 15) ++#define Z_EROFS_LI_PARTIAL_REF (1 << 15) + + /* + * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the + * compressed block count of a compressed extent (in logical clusters, aka. + * block count of a pcluster). + */ +-#define Z_EROFS_VLE_DI_D0_CBLKCNT (1 << 11) ++#define Z_EROFS_LI_D0_CBLKCNT (1 << 11) + +-struct z_erofs_vle_decompressed_index { ++struct z_erofs_lcluster_index { + __le16 di_advise; + /* where to decompress in the head lcluster */ + __le16 di_clusterofs; +@@ -401,25 +397,8 @@ struct z_erofs_vle_decompressed_index { + } di_u; + }; + +-#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \ +- (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \ +- sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING) +- +-/* dirent sorts in alphabet order, thus we can do binary search */ +-struct erofs_dirent { +- __le64 nid; /* node number */ +- __le16 nameoff; /* start offset of file name */ +- __u8 file_type; /* file type */ +- __u8 reserved; /* reserved */ +-} __packed; +- +-/* +- * EROFS file types should match generic FT_* types and +- * it seems no need to add BUILD_BUG_ONs since potential +- * unmatchness will break other fses as well... +- */ +- +-#define EROFS_NAME_LEN 255 ++#define Z_EROFS_FULL_INDEX_ALIGN(end) \ ++ (ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8) + + /* check the EROFS on-disk layout strictly at compile time */ + static inline void erofs_check_ondisk_layout_definitions(void) +@@ -436,15 +415,15 @@ static inline void erofs_check_ondisk_la + BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4); + BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8); + BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); +- BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8); ++ BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8); + BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); + /* keep in sync between 2 index structures for better extendibility */ + BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != +- sizeof(struct z_erofs_vle_decompressed_index)); ++ sizeof(struct z_erofs_lcluster_index)); + BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128); + +- BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) < +- Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1); ++ BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) < ++ Z_EROFS_LCLUSTER_TYPE_MAX - 1); + /* exclude old compiler versions like gcc 7.5.0 */ + BUILD_BUG_ON(__builtin_constant_p(fmh) ? + fmh != cpu_to_le64(1ULL << 63) : 0); +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -14,7 +14,7 @@ int z_erofs_fill_inode(struct inode *ino + + if (!erofs_sb_has_big_pcluster(sbi) && + !erofs_sb_has_ztailpacking(sbi) && !erofs_sb_has_fragments(sbi) && +- vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { ++ vi->datalayout == EROFS_INODE_COMPRESSED_FULL) { + vi->z_advise = 0; + vi->z_algorithmtype[0] = 0; + vi->z_algorithmtype[1] = 0; +@@ -45,11 +45,10 @@ static int legacy_load_cluster_from_disk + { + struct inode *const inode = m->inode; + struct erofs_inode *const vi = EROFS_I(inode); +- const erofs_off_t pos = +- Z_EROFS_VLE_LEGACY_INDEX_ALIGN(erofs_iloc(inode) + +- vi->inode_isize + vi->xattr_isize) + +- lcn * sizeof(struct z_erofs_vle_decompressed_index); +- struct z_erofs_vle_decompressed_index *di; ++ const erofs_off_t pos = Z_EROFS_FULL_INDEX_ALIGN(erofs_iloc(inode) + ++ vi->inode_isize + vi->xattr_isize) + ++ lcn * sizeof(struct z_erofs_lcluster_index); ++ struct z_erofs_lcluster_index *di; + unsigned int advise, type; + + m->kaddr = erofs_read_metabuf(&m->map->buf, inode->i_sb, +@@ -57,33 +56,33 @@ static int legacy_load_cluster_from_disk + if (IS_ERR(m->kaddr)) + return PTR_ERR(m->kaddr); + +- m->nextpackoff = pos + sizeof(struct z_erofs_vle_decompressed_index); ++ m->nextpackoff = pos + sizeof(struct z_erofs_lcluster_index); + m->lcn = lcn; + di = m->kaddr + erofs_blkoff(inode->i_sb, pos); + + advise = le16_to_cpu(di->di_advise); +- type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) & +- ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1); ++ type = (advise >> Z_EROFS_LI_LCLUSTER_TYPE_BIT) & ++ ((1 << Z_EROFS_LI_LCLUSTER_TYPE_BITS) - 1); + switch (type) { +- case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: ++ case Z_EROFS_LCLUSTER_TYPE_NONHEAD: + m->clusterofs = 1 << vi->z_logical_clusterbits; + m->delta[0] = le16_to_cpu(di->di_u.delta[0]); +- if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) { ++ if (m->delta[0] & Z_EROFS_LI_D0_CBLKCNT) { + if (!(vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | + Z_EROFS_ADVISE_BIG_PCLUSTER_2))) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + m->compressedblks = m->delta[0] & +- ~Z_EROFS_VLE_DI_D0_CBLKCNT; ++ ~Z_EROFS_LI_D0_CBLKCNT; + m->delta[0] = 1; + } + m->delta[1] = le16_to_cpu(di->di_u.delta[1]); + break; +- case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2: +- if (advise & Z_EROFS_VLE_DI_PARTIAL_REF) ++ case Z_EROFS_LCLUSTER_TYPE_PLAIN: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD1: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD2: ++ if (advise & Z_EROFS_LI_PARTIAL_REF) + m->partialref = true; + m->clusterofs = le16_to_cpu(di->di_clusterofs); + if (m->clusterofs >= 1 << vi->z_logical_clusterbits) { +@@ -125,13 +124,13 @@ static int get_compacted_la_distance(uns + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + +- if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) ++ if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) + return d1; + ++d1; + } while (++i < vcnt); + +- /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */ +- if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT)) ++ /* vcnt - 1 (Z_EROFS_LCLUSTER_TYPE_NONHEAD) item */ ++ if (!(lo & Z_EROFS_LI_D0_CBLKCNT)) + d1 += lo - 1; + return d1; + } +@@ -169,19 +168,19 @@ static int unpack_compacted_index(struct + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + m->type = type; +- if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { ++ if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { + m->clusterofs = 1 << lclusterbits; + + /* figure out lookahead_distance: delta[1] if needed */ + if (lookahead) + m->delta[1] = get_compacted_la_distance(lclusterbits, + encodebits, vcnt, in, i); +- if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { ++ if (lo & Z_EROFS_LI_D0_CBLKCNT) { + if (!big_pcluster) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } +- m->compressedblks = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; ++ m->compressedblks = lo & ~Z_EROFS_LI_D0_CBLKCNT; + m->delta[0] = 1; + return 0; + } else if (i + 1 != (int)vcnt) { +@@ -195,9 +194,9 @@ static int unpack_compacted_index(struct + */ + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * (i - 1), &type); +- if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) ++ if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) + lo = 0; +- else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) ++ else if (lo & Z_EROFS_LI_D0_CBLKCNT) + lo = 1; + m->delta[0] = lo + 1; + return 0; +@@ -211,7 +210,7 @@ static int unpack_compacted_index(struct + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); +- if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) ++ if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) + i -= lo; + + if (i >= 0) +@@ -223,10 +222,10 @@ static int unpack_compacted_index(struct + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); +- if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { +- if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { ++ if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { ++ if (lo & Z_EROFS_LI_D0_CBLKCNT) { + --i; +- nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; ++ nblk += lo & ~Z_EROFS_LI_D0_CBLKCNT; + continue; + } + /* bigpcluster shouldn't have plain d0 == 1 */ +@@ -301,10 +300,10 @@ static int z_erofs_load_cluster_from_dis + { + const unsigned int datamode = EROFS_I(m->inode)->datalayout; + +- if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) ++ if (datamode == EROFS_INODE_COMPRESSED_FULL) + return legacy_load_cluster_from_disk(m, lcn); + +- if (datamode == EROFS_INODE_FLAT_COMPRESSION) ++ if (datamode == EROFS_INODE_COMPRESSED_COMPACT) + return compacted_load_cluster_from_disk(m, lcn, lookahead); + + return -EINVAL; +@@ -326,7 +325,7 @@ static int z_erofs_extent_lookback(struc + return err; + + switch (m->type) { +- case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: ++ case Z_EROFS_LCLUSTER_TYPE_NONHEAD: + if (!m->delta[0]) { + erofs_err(m->inode->i_sb, + "invalid lookback distance 0 @ nid %llu", +@@ -336,9 +335,9 @@ static int z_erofs_extent_lookback(struc + } + lookback_distance = m->delta[0]; + continue; +- case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2: ++ case Z_EROFS_LCLUSTER_TYPE_PLAIN: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD1: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD2: + m->headtype = m->type; + m->map->m_la = (lcn << lclusterbits) | m->clusterofs; + return 0; +@@ -367,15 +366,15 @@ static int z_erofs_get_extent_compressed + unsigned long lcn; + int err; + +- DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN && +- m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 && +- m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD2); ++ DBG_BUGON(m->type != Z_EROFS_LCLUSTER_TYPE_PLAIN && ++ m->type != Z_EROFS_LCLUSTER_TYPE_HEAD1 && ++ m->type != Z_EROFS_LCLUSTER_TYPE_HEAD2); + DBG_BUGON(m->type != m->headtype); + +- if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN || +- ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1) && ++ if (m->headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN || ++ ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD1) && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) || +- ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) && ++ ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2))) { + map->m_plen = 1ULL << lclusterbits; + return 0; +@@ -397,19 +396,19 @@ static int z_erofs_get_extent_compressed + * BUG_ON in the debugging mode only for developers to notice that. + */ + DBG_BUGON(lcn == initial_lcn && +- m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD); ++ m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD); + + switch (m->type) { +- case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2: ++ case Z_EROFS_LCLUSTER_TYPE_PLAIN: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD1: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD2: + /* + * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type + * rather than CBLKCNT, it's a 1 lcluster-sized pcluster. + */ + m->compressedblks = 1 << (lclusterbits - sb->s_blocksize_bits); + break; +- case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: ++ case Z_EROFS_LCLUSTER_TYPE_NONHEAD: + if (m->delta[0] != 1) + goto err_bonus_cblkcnt; + if (m->compressedblks) +@@ -453,12 +452,12 @@ static int z_erofs_get_extent_decompress + if (err) + return err; + +- if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { ++ if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { + DBG_BUGON(!m->delta[1] && + m->clusterofs != 1 << lclusterbits); +- } else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN || +- m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 || +- m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) { ++ } else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN || ++ m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 || ++ m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) { + /* go on until the next HEAD lcluster */ + if (lcn != headlcn) + break; +@@ -477,8 +476,7 @@ static int z_erofs_get_extent_decompress + } + + static int z_erofs_do_map_blocks(struct inode *inode, +- struct erofs_map_blocks *map, +- int flags) ++ struct erofs_map_blocks *map, int flags) + { + struct erofs_inode *const vi = EROFS_I(inode); + bool ztailpacking = vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER; +@@ -508,9 +506,9 @@ static int z_erofs_do_map_blocks(struct + end = (m.lcn + 1ULL) << lclusterbits; + + switch (m.type) { +- case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1: +- case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2: ++ case Z_EROFS_LCLUSTER_TYPE_PLAIN: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD1: ++ case Z_EROFS_LCLUSTER_TYPE_HEAD2: + if (endoff >= m.clusterofs) { + m.headtype = m.type; + map->m_la = (m.lcn << lclusterbits) | m.clusterofs; +@@ -535,7 +533,7 @@ static int z_erofs_do_map_blocks(struct + map->m_flags |= EROFS_MAP_FULL_MAPPED; + m.delta[0] = 1; + fallthrough; +- case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: ++ case Z_EROFS_LCLUSTER_TYPE_NONHEAD: + /* get the corresponding first chunk */ + err = z_erofs_extent_lookback(&m, m.delta[0]); + if (err) +@@ -556,7 +554,7 @@ static int z_erofs_do_map_blocks(struct + vi->z_tailextent_headlcn = m.lcn; + /* for non-compact indexes, fragmentoff is 64 bits */ + if (fragment && +- vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) ++ vi->datalayout == EROFS_INODE_COMPRESSED_FULL) + vi->z_fragmentoff |= (u64)m.pblk << 32; + } + if (ztailpacking && m.lcn == vi->z_tailextent_headlcn) { +@@ -572,7 +570,7 @@ static int z_erofs_do_map_blocks(struct + goto unmap_out; + } + +- if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) { ++ if (m.headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN) { + if (map->m_llen > map->m_plen) { + DBG_BUGON(1); + err = -EFSCORRUPTED; +@@ -582,7 +580,7 @@ static int z_erofs_do_map_blocks(struct + Z_EROFS_COMPRESSION_INTERLACED : + Z_EROFS_COMPRESSION_SHIFTED; + } else { +- afmt = m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2 ? ++ afmt = m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2 ? + vi->z_algorithmtype[1] : vi->z_algorithmtype[0]; + if (!(EROFS_I_SB(inode)->available_compr_algs & (1 << afmt))) { + erofs_err(inode->i_sb, "inconsistent algorithmtype %u for nid %llu", +@@ -676,7 +674,7 @@ static int z_erofs_fill_inode_lazy(struc + err = -EFSCORRUPTED; + goto out_put_metabuf; + } +- if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION && ++ if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^ + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { + erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu", diff --git a/queue-6.1/series b/queue-6.1/series index 443a1256a5..ab00662f8b 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -56,3 +56,6 @@ revert-drm-amdgpu-rework-resume-handling-for-display-v2.patch rdma-rxe-fix-the-qp-flush-warnings-in-req.patch scsi-sg-fix-slab-use-after-free-read-in-sg_release.patch revert-regmap-detach-regmap-from-dev-on-regmap_exit.patch +wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch +erofs-tidy-up-erofs-on-disk-naming.patch +erofs-handle-nonhead-delta-lclusters-gracefully.patch diff --git a/queue-6.1/wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch b/queue-6.1/wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch new file mode 100644 index 0000000000..1b4b8d5a54 --- /dev/null +++ b/queue-6.1/wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch @@ -0,0 +1,91 @@ +From 95c38953cb1ecf40399a676a1f85dfe2b5780a9a Mon Sep 17 00:00:00 2001 +From: Kang Yang +Date: Tue, 8 Oct 2024 10:22:46 +0800 +Subject: wifi: ath10k: avoid NULL pointer error during sdio remove +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kang Yang + +commit 95c38953cb1ecf40399a676a1f85dfe2b5780a9a upstream. + +When running 'rmmod ath10k', ath10k_sdio_remove() will free sdio +workqueue by destroy_workqueue(). But if CONFIG_INIT_ON_FREE_DEFAULT_ON +is set to yes, kernel panic will happen: +Call trace: + destroy_workqueue+0x1c/0x258 + ath10k_sdio_remove+0x84/0x94 + sdio_bus_remove+0x50/0x16c + device_release_driver_internal+0x188/0x25c + device_driver_detach+0x20/0x2c + +This is because during 'rmmod ath10k', ath10k_sdio_remove() will call +ath10k_core_destroy() before destroy_workqueue(). wiphy_dev_release() +will finally be called in ath10k_core_destroy(). This function will free +struct cfg80211_registered_device *rdev and all its members, including +wiphy, dev and the pointer of sdio workqueue. Then the pointer of sdio +workqueue will be set to NULL due to CONFIG_INIT_ON_FREE_DEFAULT_ON. + +After device release, destroy_workqueue() will use NULL pointer then the +kernel panic happen. + +Call trace: +ath10k_sdio_remove + ->ath10k_core_unregister + …… + ->ath10k_core_stop + ->ath10k_hif_stop + ->ath10k_sdio_irq_disable + ->ath10k_hif_power_down + ->del_timer_sync(&ar_sdio->sleep_timer) + ->ath10k_core_destroy + ->ath10k_mac_destroy + ->ieee80211_free_hw + ->wiphy_free + …… + ->wiphy_dev_release + ->destroy_workqueue + +Need to call destroy_workqueue() before ath10k_core_destroy(), free +the work queue buffer first and then free pointer of work queue by +ath10k_core_destroy(). This order matches the error path order in +ath10k_sdio_probe(). + +No work will be queued on sdio workqueue between it is destroyed and +ath10k_core_destroy() is called. Based on the call_stack above, the +reason is: +Only ath10k_sdio_sleep_timer_handler(), ath10k_sdio_hif_tx_sg() and +ath10k_sdio_irq_disable() will queue work on sdio workqueue. +Sleep timer will be deleted before ath10k_core_destroy() in +ath10k_hif_power_down(). +ath10k_sdio_irq_disable() only be called in ath10k_hif_stop(). +ath10k_core_unregister() will call ath10k_hif_power_down() to stop hif +bus, so ath10k_sdio_hif_tx_sg() won't be called anymore. + +Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00189 + +Signed-off-by: Kang Yang +Tested-by: David Ruth +Reviewed-by: David Ruth +Link: https://patch.msgid.link/20241008022246.1010-1-quic_kangyang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath10k/sdio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -2647,9 +2647,9 @@ static void ath10k_sdio_remove(struct sd + + netif_napi_del(&ar->napi); + +- ath10k_core_destroy(ar); +- + destroy_workqueue(ar_sdio->workqueue); ++ ++ ath10k_core_destroy(ar); + } + + static const struct sdio_device_id ath10k_sdio_devices[] = {