OSDN Git Service

erofs: clean up z_erofs_extent_lookback
authorGao Xiang <hsiangkao@linux.alibaba.com>
Thu, 10 Mar 2022 18:27:42 +0000 (02:27 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Wed, 16 Mar 2022 16:08:48 +0000 (00:08 +0800)
Avoid the unnecessary tail recursion since it can be converted into
a loop directly in order to prevent potential stack overflow.

It's a pretty straightforward conversion.

Link: https://lore.kernel.org/r/20220310182743.102365-1-hsiangkao@linux.alibaba.com
Reviewed-by: Yue Hu <huyue2@coolpad.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
fs/erofs/zmap.c

index b4059b9..572f0b8 100644 (file)
@@ -431,48 +431,47 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
                                   unsigned int lookback_distance)
 {
        struct erofs_inode *const vi = EROFS_I(m->inode);
-       struct erofs_map_blocks *const map = m->map;
        const unsigned int lclusterbits = vi->z_logical_clusterbits;
-       unsigned long lcn = m->lcn;
-       int err;
 
-       if (lcn < lookback_distance) {
-               erofs_err(m->inode->i_sb,
-                         "bogus lookback distance @ nid %llu", vi->nid);
-               DBG_BUGON(1);
-               return -EFSCORRUPTED;
-       }
+       while (m->lcn >= lookback_distance) {
+               unsigned long lcn = m->lcn - lookback_distance;
+               int err;
 
-       /* load extent head logical cluster if needed */
-       lcn -= lookback_distance;
-       err = z_erofs_load_cluster_from_disk(m, lcn, false);
-       if (err)
-               return err;
+               /* load extent head logical cluster if needed */
+               err = z_erofs_load_cluster_from_disk(m, lcn, false);
+               if (err)
+                       return err;
 
-       switch (m->type) {
-       case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
-               if (!m->delta[0]) {
+               switch (m->type) {
+               case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+                       if (!m->delta[0]) {
+                               erofs_err(m->inode->i_sb,
+                                         "invalid lookback distance 0 @ nid %llu",
+                                         vi->nid);
+                               DBG_BUGON(1);
+                               return -EFSCORRUPTED;
+                       }
+                       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:
+                       m->headtype = m->type;
+                       m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
+                       return 0;
+               default:
                        erofs_err(m->inode->i_sb,
-                                 "invalid lookback distance 0 @ nid %llu",
-                                 vi->nid);
+                                 "unknown type %u @ lcn %lu of nid %llu",
+                                 m->type, lcn, vi->nid);
                        DBG_BUGON(1);
-                       return -EFSCORRUPTED;
+                       return -EOPNOTSUPP;
                }
-               return z_erofs_extent_lookback(m, m->delta[0]);
-       case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
-               m->headtype = m->type;
-               map->m_la = (lcn << lclusterbits) | m->clusterofs;
-               break;
-       default:
-               erofs_err(m->inode->i_sb,
-                         "unknown type %u @ lcn %lu of nid %llu",
-                         m->type, lcn, vi->nid);
-               DBG_BUGON(1);
-               return -EOPNOTSUPP;
        }
-       return 0;
+
+       erofs_err(m->inode->i_sb, "bogus lookback distance @ nid %llu",
+                 vi->nid);
+       DBG_BUGON(1);
+       return -EFSCORRUPTED;
 }
 
 static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,