]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jan 2025 13:30:50 +0000 (14:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jan 2025 13:30:50 +0000 (14:30 +0100)
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

queue-6.1/erofs-handle-nonhead-delta-lclusters-gracefully.patch [new file with mode: 0644]
queue-6.1/erofs-tidy-up-erofs-on-disk-naming.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/wifi-ath10k-avoid-null-pointer-error-during-sdio-remove.patch [new file with mode: 0644]

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 (file)
index 0000000..0e80837
--- /dev/null
@@ -0,0 +1,85 @@
+From 0bc8061ffc733a0a246b8689b2d32a3e9204f43c Mon Sep 17 00:00:00 2001
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+Date: Sat, 16 Nov 2024 01:36:51 +0800
+Subject: erofs: handle NONHEAD !delta[1] lclusters gracefully
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+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 <hsiangkao@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20241115173651.3339514-1-hsiangkao@linux.alibaba.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0471e22
--- /dev/null
@@ -0,0 +1,602 @@
+From 1c7f49a76773bcf95d3c840cff6cd449114ddf56 Mon Sep 17 00:00:00 2001
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+Date: Fri, 31 Mar 2023 14:31:49 +0800
+Subject: erofs: tidy up EROFS on-disk naming
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+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 <hsiangkao@linux.alibaba.com>
+Reviewed-by: Yue Hu <huyue2@coolpad.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Link: https://lore.kernel.org/r/20230331063149.25611-1-hsiangkao@linux.alibaba.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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",
index 443a1256a54368e1464bcb2b00ad07bea787b576..ab00662f8b56764b69f9c50985c24ffe7bf3e3c7 100644 (file)
@@ -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 (file)
index 0000000..1b4b8d5
--- /dev/null
@@ -0,0 +1,91 @@
+From 95c38953cb1ecf40399a676a1f85dfe2b5780a9a Mon Sep 17 00:00:00 2001
+From: Kang Yang <quic_kangyang@quicinc.com>
+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 <quic_kangyang@quicinc.com>
+
+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 <quic_kangyang@quicinc.com>
+Tested-by: David Ruth <druth@chromium.org>
+Reviewed-by: David Ruth <druth@chromium.org>
+Link: https://patch.msgid.link/20241008022246.1010-1-quic_kangyang@quicinc.com
+Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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[] = {