* [PATCH RESEND 02/10] staging: erofs: rearrange vle clustertype definitions
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-10 20:10 ` [PATCH v2 03/10] staging: erofs: fix vle_decompressed_index_clusterofs Gao Xiang
` (7 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch moves vle clustertype definitions to erofs_fs.h
since they are part of on-disk format.
It also adds compile time check for Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS
Reviewed-by: Chao Yu <yuchao0 at huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
RESEND:
- add `Reviewed-by: Chao Yu <yuchao0 at huawei.com>'
- no logic change
drivers/staging/erofs/erofs_fs.h | 11 +++++++++++
drivers/staging/erofs/unzip_vle.c | 8 --------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h
index 2f8e2bf..d4bffa2 100644
--- a/drivers/staging/erofs/erofs_fs.h
+++ b/drivers/staging/erofs/erofs_fs.h
@@ -202,6 +202,14 @@ struct erofs_extent_header {
* di_u.delta[1] = distance to its corresponding tail cluster
* (di_advise could be 0, 1 or 2)
*/
+enum {
+ Z_EROFS_VLE_CLUSTER_TYPE_PLAIN,
+ Z_EROFS_VLE_CLUSTER_TYPE_HEAD,
+ Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD,
+ Z_EROFS_VLE_CLUSTER_TYPE_RESERVED,
+ Z_EROFS_VLE_CLUSTER_TYPE_MAX
+};
+
#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2
#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0
@@ -260,6 +268,9 @@ static inline void erofs_check_ondisk_layout_definitions(void)
BUILD_BUG_ON(sizeof(struct erofs_extent_header) != 16);
BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8);
BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
+
+ BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) <
+ Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1);
}
#endif
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 5032b3b..f597f07 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1416,14 +1416,6 @@ static int z_erofs_vle_normalaccess_readpages(
#define __vle_cluster_type(advise) __vle_cluster_advise(advise, \
Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT, Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS)
-enum {
- Z_EROFS_VLE_CLUSTER_TYPE_PLAIN,
- Z_EROFS_VLE_CLUSTER_TYPE_HEAD,
- Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD,
- Z_EROFS_VLE_CLUSTER_TYPE_RESERVED,
- Z_EROFS_VLE_CLUSTER_TYPE_MAX
-};
-
#define vle_cluster_type(di) \
__vle_cluster_type((di)->di_advise)
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v2 03/10] staging: erofs: fix vle_decompressed_index_clusterofs
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
2018-08-10 20:10 ` [PATCH RESEND 02/10] staging: erofs: rearrange vle clustertype definitions Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-11 14:18 ` Chao Yu
2018-08-10 20:10 ` [PATCH v3 04/10] staging: erofs: fix a missing endian conversion Gao Xiang
` (6 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch adds error handing code, and fixes a missing
endian conversion in vle_decompressed_index_clusterofs.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v2:
- change the commit message;
- I personally think this patch is clear enough, therefore I don't
spilt into more small patches.
drivers/staging/erofs/unzip_vle.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index f597f07..ae99b68 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1419,24 +1419,24 @@ static int z_erofs_vle_normalaccess_readpages(
#define vle_cluster_type(di) \
__vle_cluster_type((di)->di_advise)
-static inline unsigned
-vle_compressed_index_clusterofs(unsigned clustersize,
- struct z_erofs_vle_decompressed_index *di)
+static inline int
+vle_decompressed_index_clusterofs(unsigned int *clusterofs,
+ unsigned int clustersize,
+ struct z_erofs_vle_decompressed_index *di)
{
- debugln("%s, vle=%pK, advise=%x (type %u), clusterofs=%x blkaddr=%x",
- __func__, di, di->di_advise, vle_cluster_type(di),
- di->di_clusterofs, di->di_u.blkaddr);
-
switch (vle_cluster_type(di)) {
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+ *clusterofs = clustersize;
break;
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
- return di->di_clusterofs;
+ *clusterofs = le16_to_cpu(di->di_clusterofs);
+ break;
default:
- BUG_ON(1);
+ DBG_BUGON(1);
+ return -EIO;
}
- return clustersize;
+ return 0;
}
static inline erofs_blk_t
@@ -1581,7 +1581,11 @@ int z_erofs_map_blocks_iter(struct inode *inode,
debugln("%s, lcn %u e_blkaddr %u e_blkoff %u", __func__, lcn,
e_blkaddr, vle_extent_blkoff(inode, lcn));
- logical_cluster_ofs = vle_compressed_index_clusterofs(clustersize, di);
+ err = vle_decompressed_index_clusterofs(&logical_cluster_ofs,
+ clustersize, di);
+ if (unlikely(err))
+ goto unmap_out;
+
if (!initial) {
/* [walking mode] 'map' has been already initialized */
map->m_llen += logical_cluster_ofs;
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 04/10] staging: erofs: fix a missing endian conversion
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
2018-08-10 20:10 ` [PATCH RESEND 02/10] staging: erofs: rearrange vle clustertype definitions Gao Xiang
2018-08-10 20:10 ` [PATCH v2 03/10] staging: erofs: fix vle_decompressed_index_clusterofs Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-11 14:31 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 05/10] staging: erofs: fix integer overflow on 32-bit platform Gao Xiang
` (5 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch fixes a missing endian conversion in
vle_get_logical_extent_head.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index ae99b68..c59f4c6 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1488,6 +1488,7 @@ static erofs_off_t vle_get_logical_extent_head(
struct super_block *const sb = inode->i_sb;
const unsigned int clusterbits = EROFS_SB(sb)->clusterbits;
const unsigned int clustersize = 1 << clusterbits;
+ unsigned delta0;
if (page->index != blkaddr) {
kunmap_atomic(*kaddr_iter);
@@ -1502,12 +1503,13 @@ static erofs_off_t vle_get_logical_extent_head(
di = *kaddr_iter + vle_extent_blkoff(inode, lcn);
switch (vle_cluster_type(di)) {
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
- BUG_ON(!di->di_u.delta[0]);
- BUG_ON(lcn < di->di_u.delta[0]);
+ delta0 = le16_to_cpu(di->di_u.delta[0]);
+ DBG_BUGON(!delta0);
+ DBG_BUGON(lcn < delta0);
ofs = vle_get_logical_extent_head(inode,
page_iter, kaddr_iter,
- lcn - di->di_u.delta[0], pcn, flags);
+ lcn - delta0, pcn, flags);
break;
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
*flags ^= EROFS_MAP_ZIPPED;
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v3 05/10] staging: erofs: fix integer overflow on 32-bit platform
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (2 preceding siblings ...)
2018-08-10 20:10 ` [PATCH v3 04/10] staging: erofs: fix a missing endian conversion Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-11 14:32 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 06/10] staging: erofs: fix compression mapping beyond EOF Gao Xiang
` (4 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch fixes integer overflow on multiplication
of 32-bit lcn in z_erofs_map_blocks_iter.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index c59f4c6..6404e02 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1515,7 +1515,7 @@ static erofs_off_t vle_get_logical_extent_head(
*flags ^= EROFS_MAP_ZIPPED;
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
/* clustersize should be a power of two */
- ofs = ((unsigned long long)lcn << clusterbits) +
+ ofs = ((u64)lcn << clusterbits) +
(le16_to_cpu(di->di_clusterofs) & (clustersize - 1));
*pcn = le32_to_cpu(di->di_u.blkaddr);
break;
@@ -1597,7 +1597,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* by default, compressed */
map->m_flags |= EROFS_MAP_ZIPPED;
- end = (u64)(lcn + 1) * clustersize;
+ end = ((u64)lcn + 1) * clustersize;
cluster_type = vle_cluster_type(di);
@@ -1613,7 +1613,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
}
if (ofs_rem > logical_cluster_ofs) {
- ofs = lcn * clustersize | logical_cluster_ofs;
+ ofs = (u64)lcn * clustersize | logical_cluster_ofs;
pcn = le32_to_cpu(di->di_u.blkaddr);
break;
}
@@ -1625,7 +1625,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
err = -EIO;
goto unmap_out;
}
- end = (lcn-- * clustersize) | logical_cluster_ofs;
+ end = ((u64)lcn-- * clustersize) | logical_cluster_ofs;
/* fallthrough */
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
/* get the correspoinding first chunk */
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v3 05/10] staging: erofs: fix integer overflow on 32-bit platform
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 05/10] staging: erofs: fix integer overflow on 32-bit platform Gao Xiang
@ 2018-08-11 14:32 ` Chao Yu
2018-08-12 7:54 ` [PREVIEW] [PATCH v4 " Gao Xiang
0 siblings, 1 reply; 20+ messages in thread
From: Chao Yu @ 2018-08-11 14:32 UTC (permalink / raw)
On 2018/8/11 4:10, Gao Xiang wrote:
> This patch fixes integer overflow on multiplication
> of 32-bit lcn in z_erofs_map_blocks_iter.
>
> Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
Reviewed-by: Chao Yu <yuchao0 at huawei.com>
Thanks,
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PREVIEW] [PATCH v4 05/10] staging: erofs: fix integer overflow on 32-bit platform
2018-08-11 14:32 ` Chao Yu
@ 2018-08-12 7:54 ` Gao Xiang
0 siblings, 0 replies; 20+ messages in thread
From: Gao Xiang @ 2018-08-12 7:54 UTC (permalink / raw)
From: Gao Xiang <gaoxiang25@huawei.com>
This patch fixes integer overflow on multiplication
of 32-bit `lcn' in z_erofs_map_blocks_iter.
Reviewed-by: Chao Yu <yuchao0 at huawei.com>
Signed-off-by: Chao Yu <yuchao0 at huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v4:
- fix commit message a bit.
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 0accf1b..79d4ca0 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1513,7 +1513,7 @@ static erofs_off_t vle_get_logical_extent_head(
*flags ^= EROFS_MAP_ZIPPED;
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
/* clustersize should be a power of two */
- ofs = ((unsigned long long)lcn << clusterbits) +
+ ofs = ((u64)lcn << clusterbits) +
(le16_to_cpu(di->di_clusterofs) & (clustersize - 1));
*pcn = le32_to_cpu(di->di_u.blkaddr);
break;
@@ -1595,7 +1595,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* by default, compressed */
map->m_flags |= EROFS_MAP_ZIPPED;
- end = (u64)(lcn + 1) * clustersize;
+ end = ((u64)lcn + 1) * clustersize;
cluster_type = vle_cluster_type(di);
@@ -1611,7 +1611,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
}
if (ofs_rem > logical_cluster_ofs) {
- ofs = lcn * clustersize | logical_cluster_ofs;
+ ofs = (u64)lcn * clustersize | logical_cluster_ofs;
pcn = le32_to_cpu(di->di_u.blkaddr);
break;
}
@@ -1623,7 +1623,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
err = -EIO;
goto unmap_out;
}
- end = (lcn-- * clustersize) | logical_cluster_ofs;
+ end = ((u64)lcn-- * clustersize) | logical_cluster_ofs;
/* fallthrough */
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
/* get the correspoinding first chunk */
--
2.7.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PREVIEW] [PATCH v3 06/10] staging: erofs: fix compression mapping beyond EOF
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (3 preceding siblings ...)
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 05/10] staging: erofs: fix integer overflow on 32-bit platform Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-11 14:42 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 07/10] staging: erofs: clean up z_erofs_map_blocks_iter Gao Xiang
` (3 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
Logical address of EOF LTP mapping should start at
`inode->i_size' rather than `inode->i_size - 1' to
`m_la(in) + 1 - inode->i_size', fix it.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 6404e02..f81b2a6 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1550,7 +1550,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
if (unlikely(map->m_la >= inode->i_size)) {
BUG_ON(!initial);
map->m_llen = map->m_la + 1 - inode->i_size;
- map->m_la = inode->i_size - 1;
+ map->m_la = inode->i_size;
map->m_flags = 0;
goto out;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v3 06/10] staging: erofs: fix compression mapping beyond EOF
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 06/10] staging: erofs: fix compression mapping beyond EOF Gao Xiang
@ 2018-08-11 14:42 ` Chao Yu
2018-08-12 7:49 ` [PREVIEW] [PATCH v4 " Gao Xiang
0 siblings, 1 reply; 20+ messages in thread
From: Chao Yu @ 2018-08-11 14:42 UTC (permalink / raw)
On 2018/8/11 4:10, Gao Xiang wrote:
> Logical address of EOF LTP mapping should start at
> `inode->i_size' rather than `inode->i_size - 1' to
> `m_la(in) + 1 - inode->i_size', fix it.
>
> Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
Reviewed-by: Chao Yu <yuchao0 at huawei.com>
Thanks,
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PREVIEW] [PATCH v4 06/10] staging: erofs: fix compression mapping beyond EOF
2018-08-11 14:42 ` Chao Yu
@ 2018-08-12 7:49 ` Gao Xiang
0 siblings, 0 replies; 20+ messages in thread
From: Gao Xiang @ 2018-08-12 7:49 UTC (permalink / raw)
From: Gao Xiang <gaoxiang25@huawei.com>
Logical address of EOF LTP mapping should start at
`inode->i_size' rather than `inode->i_size - 1' to
`m_la(in)', fix it.
Reviewed-by: Chao Yu <yuchao0 at huawei.com>
Signed-off-by: Chao Yu <yuchao0 at huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v4:
- fix the description `m_la(in) + 1 - inode->i_size' to
`m_la(in)' in the commit message.
change log v3:
- spilt into small patches at Chao's suggestion.
Hi Chao,
Please help use this commit message. Thanks.
Thanks,
Gao Xiang
drivers/staging/erofs/unzip_vle.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 79d4ca0..aecf650 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1548,7 +1548,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
if (unlikely(map->m_la >= inode->i_size)) {
BUG_ON(!initial);
map->m_llen = map->m_la + 1 - inode->i_size;
- map->m_la = inode->i_size - 1;
+ map->m_la = inode->i_size;
map->m_flags = 0;
goto out;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PREVIEW] [PATCH v3 07/10] staging: erofs: clean up z_erofs_map_blocks_iter
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (4 preceding siblings ...)
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 06/10] staging: erofs: fix compression mapping beyond EOF Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-19 13:51 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 08/10] staging: erofs: complete error handing of z_erofs_map_blocks_iter Gao Xiang
` (2 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch mainly introduces `vle_map_blocks_iter_ctx' to clean up
z_erofs_map_blocks_iter and vle_get_logical_extent_head.
It changes the return value of `vle_get_logical_extent_head' to int
for the later error handing. In addition, it also renames `pcn' to
`pblk' since only `pblk' exists in erofs compression ondisk format.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 139 +++++++++++++++++++++-----------------
1 file changed, 77 insertions(+), 62 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index f81b2a6..74d2530 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1410,6 +1410,13 @@ static int z_erofs_vle_normalaccess_readpages(
.readpages = z_erofs_vle_normalaccess_readpages,
};
+/*
+ * Variable-sized Logical Extent (Fixed Physical Cluster) Compression Mode
+ * ---
+ * VLE compression mode attempts to compress a number of logical data into
+ * a physical cluster with a fixed size.
+ * VLE compression mode uses "struct z_erofs_vle_decompressed_index".
+ */
#define __vle_cluster_advise(x, bit, bits) \
((le16_to_cpu(x) >> (bit)) & ((1 << (bits)) - 1))
@@ -1465,90 +1472,95 @@ static int z_erofs_vle_normalaccess_readpages(
return erofs_blkoff(iloc(sbi, vi->nid) + ofs);
}
-/*
- * Variable-sized Logical Extent (Fixed Physical Cluster) Compression Mode
- * ---
- * VLE compression mode attempts to compress a number of logical data into
- * a physical cluster with a fixed size.
- * VLE compression mode uses "struct z_erofs_vle_decompressed_index".
- */
-static erofs_off_t vle_get_logical_extent_head(
- struct inode *inode,
- struct page **page_iter,
- void **kaddr_iter,
- unsigned lcn, /* logical cluster number */
- erofs_blk_t *pcn,
- unsigned *flags)
+struct vle_map_blocks_iter_ctx {
+ struct inode *inode;
+ struct super_block *sb;
+ unsigned int clusterbits;
+
+ struct page **mpage_ret;
+ void **kaddr_ret;
+};
+
+static int
+vle_get_logical_extent_head(const struct vle_map_blocks_iter_ctx *ctx,
+ unsigned int lcn, /* logical cluster number */
+ unsigned long long *ofs,
+ erofs_blk_t *pblk,
+ unsigned int *flags)
{
- /* for extent meta */
- struct page *page = *page_iter;
- erofs_blk_t blkaddr = vle_extent_blkaddr(inode, lcn);
+ const unsigned int clustersize = 1 << ctx->clusterbits;
+ const erofs_blk_t mblk = vle_extent_blkaddr(ctx->inode, lcn);
+ struct page *mpage = *ctx->mpage_ret; /* extent metapage */
+
struct z_erofs_vle_decompressed_index *di;
- unsigned long long ofs;
- struct super_block *const sb = inode->i_sb;
- const unsigned int clusterbits = EROFS_SB(sb)->clusterbits;
- const unsigned int clustersize = 1 << clusterbits;
- unsigned delta0;
-
- if (page->index != blkaddr) {
- kunmap_atomic(*kaddr_iter);
- unlock_page(page);
- put_page(page);
+ unsigned int cluster_type, delta0;
+
+ if (mpage->index != mblk) {
+ kunmap_atomic(*ctx->kaddr_ret);
+ unlock_page(mpage);
+ put_page(mpage);
- page = erofs_get_meta_page_nofail(sb, blkaddr, false);
- *page_iter = page;
- *kaddr_iter = kmap_atomic(page);
+ mpage = erofs_get_meta_page_nofail(ctx->sb, mblk, false);
+ *ctx->mpage_ret = mpage;
+ *ctx->kaddr_ret = kmap_atomic(mpage);
}
- di = *kaddr_iter + vle_extent_blkoff(inode, lcn);
- switch (vle_cluster_type(di)) {
+ di = *ctx->kaddr_ret + vle_extent_blkoff(ctx->inode, lcn);
+
+ cluster_type = vle_cluster_type(di);
+ switch (cluster_type) {
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
delta0 = le16_to_cpu(di->di_u.delta[0]);
DBG_BUGON(!delta0);
DBG_BUGON(lcn < delta0);
- ofs = vle_get_logical_extent_head(inode,
- page_iter, kaddr_iter,
- lcn - delta0, pcn, flags);
- break;
+ return vle_get_logical_extent_head(ctx,
+ lcn - delta0, ofs, pblk, flags);
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
*flags ^= EROFS_MAP_ZIPPED;
+ /* fallthrough */
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
/* clustersize should be a power of two */
- ofs = ((u64)lcn << clusterbits) +
+ *ofs = ((u64)lcn << ctx->clusterbits) +
(le16_to_cpu(di->di_clusterofs) & (clustersize - 1));
- *pcn = le32_to_cpu(di->di_u.blkaddr);
+ *pblk = le32_to_cpu(di->di_u.blkaddr);
break;
default:
BUG_ON(1);
}
- return ofs;
+ return 0;
}
int z_erofs_map_blocks_iter(struct inode *inode,
struct erofs_map_blocks *map,
struct page **mpage_ret, int flags)
{
+ void *kaddr;
+ const struct vle_map_blocks_iter_ctx ctx = {
+ .inode = inode,
+ .sb = inode->i_sb,
+ .clusterbits = EROFS_I_SB(inode)->clusterbits,
+ .mpage_ret = mpage_ret,
+ .kaddr_ret = &kaddr
+ };
+ const unsigned int clustersize = 1 << ctx.clusterbits;
+ /* if both m_(l,p)len are 0, regularize l_lblk, l_lofs, etc... */
+ const bool initial = !map->m_llen;
+
/* logicial extent (start, end) offset */
unsigned long long ofs, end;
- struct z_erofs_vle_decompressed_index *di;
- erofs_blk_t e_blkaddr, pcn;
- unsigned lcn, logical_cluster_ofs, cluster_type;
+ unsigned int lcn;
u32 ofs_rem;
+
+ erofs_blk_t mblk, pblk;
struct page *mpage = *mpage_ret;
- void *kaddr;
- bool initial;
- struct super_block *const sb = inode->i_sb;
- const unsigned int clusterbits = EROFS_SB(sb)->clusterbits;
- const unsigned int clustersize = 1 << clusterbits;
+ struct z_erofs_vle_decompressed_index *di;
+ unsigned int cluster_type, logical_cluster_ofs;
int err = 0;
- /* if both m_(l,p)len are 0, regularize l_lblk, l_lofs, etc... */
- initial = !map->m_llen;
-
/* when trying to read beyond EOF, leave it unmapped */
if (unlikely(map->m_la >= inode->i_size)) {
- BUG_ON(!initial);
+ DBG_BUGON(!initial);
map->m_llen = map->m_la + 1 - inode->i_size;
map->m_la = inode->i_size;
map->m_flags = 0;
@@ -1561,16 +1573,16 @@ int z_erofs_map_blocks_iter(struct inode *inode,
ofs = map->m_la + map->m_llen;
/* clustersize should be power of two */
- lcn = ofs >> clusterbits;
+ lcn = ofs >> ctx.clusterbits;
ofs_rem = ofs & (clustersize - 1);
- e_blkaddr = vle_extent_blkaddr(inode, lcn);
+ mblk = vle_extent_blkaddr(inode, lcn);
- if (mpage == NULL || mpage->index != e_blkaddr) {
+ if (mpage == NULL || mpage->index != mblk) {
if (mpage != NULL)
put_page(mpage);
- mpage = erofs_get_meta_page_nofail(sb, e_blkaddr, false);
+ mpage = erofs_get_meta_page_nofail(ctx.sb, mblk, false);
*mpage_ret = mpage;
} else {
lock_page(mpage);
@@ -1580,8 +1592,8 @@ int z_erofs_map_blocks_iter(struct inode *inode,
kaddr = kmap_atomic(mpage);
di = kaddr + vle_extent_blkoff(inode, lcn);
- debugln("%s, lcn %u e_blkaddr %u e_blkoff %u", __func__, lcn,
- e_blkaddr, vle_extent_blkoff(inode, lcn));
+ debugln("%s, lcn %u mblk %u e_blkoff %u", __func__, lcn,
+ mblk, vle_extent_blkoff(inode, lcn));
err = vle_decompressed_index_clusterofs(&logical_cluster_ofs,
clustersize, di);
@@ -1608,13 +1620,13 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* fallthrough */
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
if (ofs_rem == logical_cluster_ofs) {
- pcn = le32_to_cpu(di->di_u.blkaddr);
+ pblk = le32_to_cpu(di->di_u.blkaddr);
goto exact_hitted;
}
if (ofs_rem > logical_cluster_ofs) {
ofs = (u64)lcn * clustersize | logical_cluster_ofs;
- pcn = le32_to_cpu(di->di_u.blkaddr);
+ pblk = le32_to_cpu(di->di_u.blkaddr);
break;
}
@@ -1629,9 +1641,12 @@ int z_erofs_map_blocks_iter(struct inode *inode,
/* fallthrough */
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
/* get the correspoinding first chunk */
- ofs = vle_get_logical_extent_head(inode, mpage_ret,
- &kaddr, lcn, &pcn, &map->m_flags);
+ err = vle_get_logical_extent_head(&ctx, lcn, &ofs,
+ &pblk, &map->m_flags);
mpage = *mpage_ret;
+
+ if (unlikely(err))
+ goto unmap_out;
break;
default:
errln("unknown cluster type %u at offset %llu of nid %llu",
@@ -1644,7 +1659,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
exact_hitted:
map->m_llen = end - ofs;
map->m_plen = clustersize;
- map->m_pa = blknr_to_addr(pcn);
+ map->m_pa = blknr_to_addr(pblk);
map->m_flags |= EROFS_MAP_MAPPED;
unmap_out:
kunmap_atomic(kaddr);
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v3 08/10] staging: erofs: complete error handing of z_erofs_map_blocks_iter
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (5 preceding siblings ...)
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 07/10] staging: erofs: clean up z_erofs_map_blocks_iter Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-19 13:51 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v2 09/10] staging: erofs: fix a bug when appling cache strategy Gao Xiang
2018-08-10 20:10 ` [PREVIEW] [PATCH v2 10/10] staging: erofs: complete error handing of z_erofs_do_read_page Gao Xiang
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch completes error handing of z_erofs_map_blocks_iter
and vle_get_logical_extent_head, including no memory and
io error cases.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v3:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 74d2530..6c93877 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -1500,7 +1500,11 @@ struct vle_map_blocks_iter_ctx {
unlock_page(mpage);
put_page(mpage);
- mpage = erofs_get_meta_page_nofail(ctx->sb, mblk, false);
+ mpage = erofs_get_meta_page(ctx->sb, mblk, false);
+ if (IS_ERR(mpage)) {
+ *ctx->mpage_ret = NULL;
+ return PTR_ERR(mpage);
+ }
*ctx->mpage_ret = mpage;
*ctx->kaddr_ret = kmap_atomic(mpage);
}
@@ -1511,9 +1515,12 @@ struct vle_map_blocks_iter_ctx {
switch (cluster_type) {
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
delta0 = le16_to_cpu(di->di_u.delta[0]);
- DBG_BUGON(!delta0);
- DBG_BUGON(lcn < delta0);
-
+ if (unlikely(!delta0 || delta0 > lcn)) {
+ errln("invalid NONHEAD dl0 %u at lcn %u of nid %llu",
+ delta0, lcn, EROFS_V(ctx->inode)->nid);
+ DBG_BUGON(1);
+ return -EIO;
+ }
return vle_get_logical_extent_head(ctx,
lcn - delta0, ofs, pblk, flags);
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
@@ -1526,7 +1533,10 @@ struct vle_map_blocks_iter_ctx {
*pblk = le32_to_cpu(di->di_u.blkaddr);
break;
default:
- BUG_ON(1);
+ errln("unknown cluster type %u at lcn %u of nid %llu",
+ cluster_type, lcn, EROFS_V(ctx->inode)->nid);
+ DBG_BUGON(1);
+ return -EIO;
}
return 0;
}
@@ -1582,7 +1592,11 @@ int z_erofs_map_blocks_iter(struct inode *inode,
if (mpage != NULL)
put_page(mpage);
- mpage = erofs_get_meta_page_nofail(ctx.sb, mblk, false);
+ mpage = erofs_get_meta_page(ctx.sb, mblk, false);
+ if (IS_ERR(mpage)) {
+ err = PTR_ERR(mpage);
+ goto out;
+ }
*mpage_ret = mpage;
} else {
lock_page(mpage);
@@ -1645,8 +1659,11 @@ int z_erofs_map_blocks_iter(struct inode *inode,
&pblk, &map->m_flags);
mpage = *mpage_ret;
- if (unlikely(err))
- goto unmap_out;
+ if (unlikely(err)) {
+ if (mpage != NULL)
+ goto unmap_out;
+ goto out;
+ }
break;
default:
errln("unknown cluster type %u at offset %llu of nid %llu",
@@ -1670,7 +1687,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
map->m_llen, map->m_plen, map->m_flags);
/* aggressively BUG_ON iff CONFIG_EROFS_FS_DEBUG is on */
- DBG_BUGON(err < 0);
+ DBG_BUGON(err < 0 && err != -ENOMEM);
return err;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v2 09/10] staging: erofs: fix a bug when appling cache strategy
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (6 preceding siblings ...)
2018-08-10 20:10 ` [PREVIEW] [PATCH v3 08/10] staging: erofs: complete error handing of z_erofs_map_blocks_iter Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-19 13:52 ` Chao Yu
2018-08-10 20:10 ` [PREVIEW] [PATCH v2 10/10] staging: erofs: complete error handing of z_erofs_do_read_page Gao Xiang
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
As described in Kconfig, the last compressed pack should be cached
for further reading for either `EROFS_FS_ZIP_CACHE_UNIPOLAR' or
`EROFS_FS_ZIP_CACHE_BIPOLAR' by design.
However, there is a bug in z_erofs_do_read_page, it will
switch `initial' to `false' at the very beginning before it decides
to cache the last compressed pack.
caching strategy should work properly after appling this patch.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v2:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 6c93877..1f64cb1 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -629,7 +629,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
/* go ahead the next map_blocks */
debugln("%s: [out-of-range] pos %llu", __func__, offset + cur);
- if (!z_erofs_vle_work_iter_end(builder))
+ if (z_erofs_vle_work_iter_end(builder))
fe->initial = false;
map->m_la = offset + cur;
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PREVIEW] [PATCH v2 10/10] staging: erofs: complete error handing of z_erofs_do_read_page
2018-08-10 20:10 [PATCH RESEND 01/10] staging: erofs: cleanup z_erofs_vle_work_{lookup, register} Gao Xiang
` (7 preceding siblings ...)
2018-08-10 20:10 ` [PREVIEW] [PATCH v2 09/10] staging: erofs: fix a bug when appling cache strategy Gao Xiang
@ 2018-08-10 20:10 ` Gao Xiang
2018-08-19 13:52 ` Chao Yu
8 siblings, 1 reply; 20+ messages in thread
From: Gao Xiang @ 2018-08-10 20:10 UTC (permalink / raw)
This patch completes error handing code of z_erofs_do_read_page.
PG_error will be set when some read error happens, therefore
z_erofs_onlinepage_endio will unlock this page without setting
PG_uptodate.
Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com>
---
change log v2:
- spilt into small patches at Chao's suggestion.
drivers/staging/erofs/unzip_vle.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c
index 1f64cb1..1d0ffa6 100644
--- a/drivers/staging/erofs/unzip_vle.c
+++ b/drivers/staging/erofs/unzip_vle.c
@@ -611,7 +611,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
enum z_erofs_page_type page_type;
unsigned cur, end, spiltted, index;
- int err;
+ int err = 0;
/* register locked file pages as online pages in pack */
z_erofs_onlinepage_init(page);
@@ -638,12 +638,11 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
if (unlikely(err))
goto err_out;
- /* deal with hole (FIXME! broken now) */
if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED)))
goto hitted;
DBG_BUGON(map->m_plen != 1 << sbi->clusterbits);
- BUG_ON(erofs_blkoff(map->m_pa));
+ DBG_BUGON(erofs_blkoff(map->m_pa));
err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head);
if (unlikely(err))
@@ -688,7 +687,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
err = z_erofs_vle_work_add_page(builder,
newpage, Z_EROFS_PAGE_TYPE_EXCLUSIVE);
- if (!err)
+ if (likely(!err))
goto retry;
}
@@ -699,9 +698,10 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
/* FIXME! avoid the last relundant fixup & endio */
z_erofs_onlinepage_fixup(page, index, true);
- ++spiltted;
- /* also update nr_pages and increase queued_pages */
+ /* bump up the number of spiltted parts of a page */
+ ++spiltted;
+ /* also update nr_pages */
work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1);
next_part:
/* can be used for verification */
@@ -711,16 +711,18 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe,
if (end > 0)
goto repeat;
+out:
/* FIXME! avoid the last relundant fixup & endio */
z_erofs_onlinepage_endio(page);
debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu",
__func__, page, spiltted, map->m_llen);
- return 0;
+ return err;
+ /* if some error occurred while processing this page */
err_out:
- /* TODO: the missing error handing cases */
- return err;
+ SetPageError(page);
+ goto out;
}
static void z_erofs_vle_unzip_kickoff(void *ptr, int bios)
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread